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

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

Уважаемые читатели!
Тут можно читать бесплатно UNIX: разработка сетевых приложений - Уильям Стивенс. Жанр: Программное обеспечение. Так же Вы можете читать полную версию (весь текст) онлайн книги без регистрации и SMS на сайте Knigi-online.info (книги онлайн) или прочесть краткое содержание, описание, предисловие (аннотацию) от автора и ознакомиться с отзывами (комментариями) о произведении.
Описание онлайн-книги UNIX: разработка сетевых приложений - Уильям Стивенс:
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

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



📚 "UNIX: разработка сетевых приложений" - это увлекательное путешествие в мир UNIX и сетевого программирования. В книге автор подробно рассматривает основные принципы разработки сетевых приложений под UNIX, раскрывая множество интересных тем и примеров.



Главный герой книги - опытный разработчик, который стремится углубить свои знания в области сетевого программирования под UNIX. Он исследует различные аспекты работы с сетью, изучает протоколы передачи данных и на практике применяет полученные знания.



👨‍💻 Уильям Стивенс - известный специалист в области компьютерных наук, автор множества книг по сетевому программированию. Его работы пользуются популярностью среди разработчиков и студентов по всему миру.



На сайте knigi-online.info вы можете бесплатно и без регистрации слушать аудиокниги онлайн на русском языке. Здесь собраны бестселлеры и лучшие произведения различных жанров, чтобы каждый мог найти что-то по душе.



🎧 Погрузитесь в увлекательный мир UNIX и сетевого программирования вместе с аудиокнигой "UNIX: разработка сетевых приложений" от Уильяма Стивенса. Развивайте свои навыки, открывайте новые горизонты и наслаждайтесь процессом обучения!

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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 117 118 119 120 121 122 123 124 125 ... 263

 7  char c, argsockfd[10], argmode[10];

 8  Socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);

 9  if ((childpid = Fork()) == 0) { /* дочерний процесс */

10   Close(sockfd[0]);

11   snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]);

12   snprintf(argmode, sizeof(argmode), "%d", mode);

13   execl("./openfile", "openfile", argsockfd, pathname, argmode,

14    (char*)NULL);

15   err_sys("execl error");

16  }

17  /* родительский процесс - ожидание завершения дочернего процесса */

18  Close(sockfd[1]); /* закрываем конец, который мы не используем */

19  Waitpid(childpid, &status, 0);

20  if (WIFEXITED(status) == 0)

21   err_quit("child did not terminate");

22  if ((status = WEXITSTATUS(status)) == 0)

23   Read_fd(sockfd[0], &c, 1, &fd);

24  else {

25   errno = status; /* установка значения errno в статус дочернего

                        процесса */

26   fd = -1;

27  }

28  Close(sockfd[0]);

29  return (fd);

30 }

Создание потокового канала

8 Функция socketpair создает потоковый канал. Возвращаются два дескриптора: sockfd[0] и sockfd[1]. Это состояние, которое мы показали на рис. 15.1.

Функции fork и exec

9-16 Вызывается функция fork, после чего дочерний процесс закрывает один конец потокового канала. Номер дескриптора другого конца потокового канала помещается в массив argsockfd, а режим открытия помещается в массив argmode. Мы вызываем функцию snprintf, поскольку аргументы функции exec должны быть символьными строками. Выполняется программа openfile. Функция execl возвращает управление только в том случае, если она встретит ошибку. При удачном выполнении начинает выполняться функция main программы openfile.

Родительский процесс в ожидании завершения дочернего процесса

17-22 Родительский процесс закрывает другой конец потокового канала и вызывает функцию waitpid для ожидания завершения дочернего процесса. Статус завершения дочернего процесса возвращается в переменной status, и сначала мы проверяем, что программа завершилась нормально (то есть не была завершена из-за возникновения какого-либо сигнала). Затем макрос WEXITSTATUS преобразует статус завершения в статус выхода, значение которого должно быть между 0 и 255. Мы вскоре увидим, что если при открытии необходимого файла программой openfile происходит ошибка, то эта программа завершается, причем статус ее завершения равен соответствующему значению переменной errno.

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

23 Наша функция read_fd, которую мы показываем в следующем листинге, получает дескриптор потокового канала. Кроме получения дескриптора мы считываем 1 байт данных, но ничего с этими данными не делаем.

ПРИМЕЧАНИЕ

При отправке и получении дескриптора по потоковому каналу мы всегда отправляем как минимум 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 <sockfd#> <filename> <mode>");

 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.

1 ... 117 118 119 120 121 122 123 124 125 ... 263
На этой странице вы можете бесплатно читать книгу UNIX: разработка сетевых приложений - Уильям Стивенс бесплатно.
Похожие на UNIX: разработка сетевых приложений - Уильям Стивенс книги

Оставить комментарий

Рейтинговые книги