Уильям Стивенс - UNIX: разработка сетевых приложений

Тут можно читать онлайн Уильям Стивенс - UNIX: разработка сетевых приложений - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Питер, год 2007. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    UNIX: разработка сетевых приложений
  • Автор:
  • Жанр:
  • Издательство:
    Питер
  • Год:
    2007
  • Город:
    Санкт-Петербург
  • ISBN:
    5-94723-991-4
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание

UNIX: разработка сетевых приложений - описание и краткое содержание, автор Уильям Стивенс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок

UNIX: разработка сетевых приложений - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Уильям Стивенс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать
ПРИМЕЧАНИЕ

При отправке и получении дескриптора по потоковому каналу мы всегда отправляем как минимум 1 байт данных, даже если получатель никак эти данные не обрабатывает. Иначе получатель не сможет распознать, что значит нулевое возвращаемое значение из функции read_fd: отсутствие данных (но, возможно, есть дескриптор) или конец файла.

В листинге 15.9 показана функция readfd, вызывающая функцию recvmsgдля получения данных и дескриптора через доменный сокет Unix. Первые три аргумента этой функции те же, что и для функции read, а четвертый ( recvfd) является указателем на целое число. После выполнения этой функции recvfdбудет указывать на полученный дескриптор.

Листинг 15.9. Функция read_fd: получение данных и дескриптора

//lib/read_fd.c

1 #include "unp.h"

2 ssize_t

3 read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)

4 {

5 struct msghdr msg;

6 struct iovec iov[1];

7 ssize_t n;

8 int newfd;

9 #ifdef HAVE_MSGHDR_MSG_CONTROL

10 union {

11 struct cmsghdr cm;

12 char control[CMSG_SPACE(sizeof(int))];

13 } control_un;

14 struct cmsghdr *cmptr;

15 msg.msg_control = control_un.control;

16 msg.msg_controllen = sizeof(control_un.control);

17 #else

18 msg.msg_accrights = (caddr_t)&newfd;

19 msg.msg_accrightslen = sizeof(int);

20 #endif

21 msg.msg_name = NULL;

22 msg.msg_namelen = 0;

23 iov[0].iov_base = ptr;

24 iov[0].iov_len = nbytes;

25 msg.msg_iov = iov;

26 msg.msg_iovlen = 1;

27 if ((n = recvmsg(fd, &msg, 0)) <= 0)

28 return (n);

29 #ifdef HAVE_MSGHDR_MSG_CONTROL

30 if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&

31 mptr->cmsg_len == CMSG_LEN(sizeof(int))) {

32 if (cmptr->cmsg_level != SOL_SOCKET)

33 err_quit("control level != SOL_SOCKET");

34 if (cmptr->cmsg_type != SCM_RIGHTS)

35 err_quit("control type != SCM_RIGHTS");

36 *recvfd = *((int*)CMSG_DATA(cmptr));

37 } else

38 *recvfd = -1; /* дескриптор не был передан */

39 #else

40 if (msg.msg_accrightslen == sizeof(int))

41 *recvfd = newfd;

42 else

43 *recvfd = -1; /* дескриптор не был передан */

44 #endif

45 return (n);

46 }

8-26 Эта функция должна работать с обеими версиями функции recvmsg: с элементом msg_controlи с элементом msg_accrights. Наш заголовочный файл config.h(см. листинг Г.2) определяет константу HAVE_MSGHDR_MSG_CONTROL, если поддерживается версия функции recvmsgс msg_control.

Проверка выравнивания буфера msg_control

10-13 Буфер msg_controlдолжен быть выровнен в соответствии со структурой msghdr. Просто выделить в памяти массив типа charнедостаточно. Здесь мы объявляем объединение, состоящее из структуры cmsghdrи символьного массива, что гарантирует необходимое выравнивание массива. Возможно и другое решение — вызвать функцию malloc, но это потребует освобождения памяти перед завершением функции.

27-45 Вызывается функция recvmsg. Если возвращаются вспомогательные данные, их формат будет таким, как показано на рис. 14.4. Мы проверяем, верны ли длина, уровень и тип, затем получаем вновь созданный дескриптор и возвращаем его через указатель вызывающего процесса recvfd. Макрос CMSG_DATAвозвращает указатель на элемент cmsg_dataобъекта вспомогательных данных как указатель на элемент типа unsigned char. Мы преобразуем его к указателю на элемент типа intи получаем целочисленный дескриптор, на который указывает этот указатель.

Если поддерживается более старый элемент msg_accrights, то длина должна быть равна размеру целого числа, а вновь созданный дескриптор возвращается через указатель recvfdвызывающего процесса.

В листинге 15.10 показана программа openfile. Она получает три аргумента командной строки, которые должны быть переданы, и вызывает обычную функцию open.

Листинг 15.10. Программа openfile: открытие файла и передача дескриптора обратно

//unixdomain/openfile.c

1 #include "unp.h"

2 int

3 main(int argc, char **argv)

4 {

5 int fd;

6 ssize_t n;

7 if (argc != 4)

8 err_quit("openfile ");

9 if ((fd = open(argv[2], atoi(argv[3]))) < 0)

10 exit((errno > 0) ? errno : 255);

11 if ((n = write_fd(atoi(argv[1]), "", 1, fd)) < 0)

12 exit((errno > 0) ? errno : 255);

13 exit(0);

14 }

Аргументы командной строки

6-7 Поскольку два из трех аргументов командной строки были превращены в символьные строки функцией my_open, они преобразуются обратно в целые числа при помощи функции atoi.

Открытие файла

9-10 Файл открывается с помощью функции open. Если встречается ошибка, статус завершения этого процесса содержит значение переменной errno, соответствующее ошибке функции open.

Передача дескриптора обратно

11-12 Дескриптор передается обратно функцией write_fd, которую мы покажем в следующем листинге. Затем этот процесс завершается, но ранее в этой главе мы сказали, что отправляющий процесс может закрыть переданный дескриптор (это происходит, когда мы вызываем функцию exit), поскольку ядро знает, что дескриптор находится в состоянии передачи («в полете»), и оставляет его открытым для принимающего процесса.

ПРИМЕЧАНИЕ

Статус выхода должен лежать в пределах от 0 до 255. Максимальное значение переменной errno — около 150. Альтернативный способ, при котором не требуется, чтобы значение переменной errno было меньше 256, заключается в том, чтобы передать обратно указание на ошибку в виде обычных данных при вызове функции sendmsg.

В листинге 15.11 показана последняя функция, write_fd, вызывающая функцию sendmsgдля отправки дескриптора (и, возможно, еще каких-либо данных, которые мы не используем) через доменный сокет Unix.

Листинг 15.11. Функция write_fd: передача дескриптора при помощи вызова функции sendmsg

//lib/write_fd.c

1 #include "unp.h"

2 ssize_t

3 write_fd(int fd, void *ptr, size_t nbytes, int sendfd)

4 {

5 struct msghdr msg;

6 struct iovec iov[1];

7 #ifdef HAVE_MSGHDR_MSG_CONTROL

8 union {

9 struct cmsghdr cm;

10 char control[CMSG_SPACE(sizeof(int))];

11 } control_un;

12 struct cmsghdr *cmptr;

13 msg.msg_control = control_un.control;

14 msg.msg_controllen = sizeof(control_un.control);

15 cmptr = CMSG_FIRSTHDR(&msg);

16 cmptr->cmsg_len = CMSG_LEN(sizeof(int));

17 cmptr->cmsg_level = SOL_SOCKET;

18 cmptr->cmsg_type = SCM_RIGHTS;

19 *((int*)CMSG_DATA(cmptr)) = sendfd;

20 #else

21 msg.msg_accrights = (caddr_t)&sendfd;

22 msg.msg_accrightslen = sizeof(int);

23 #endif

24 msg.msg_name = NULL;

25 msg.msg_namelen = 0;

26 iov[0].iov_base = ptr;

27 iov[0].iov_len = nbytes;

28 msg.msg_iov = iov;

29 msg.msg_iovlen = 1;

30 return (sendmsg(fd, &msg, 0));

31 }

Как и в случае функции read_fg, эта функция обрабатывает либо вспомогательные данные, либо права доступа, которые предшествовали вспомогательным данным в более ранних реализациях. В любом случае инициализируется структура msghdrи затем вызывается функция sendmsg.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




UNIX: разработка сетевых приложений отзывы


Отзывы читателей о книге UNIX: разработка сетевых приложений, автор: Уильям Стивенс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x