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

Интервал:

Закладка:

Сделать

Правильным решением будет вызвать функцию waitpidвместо wait. В листинге 5.8 представлена версия нашей функции sigchld, корректно обрабатывающая сигнал SIGCHLD. Эта версия работает, потому что мы вызываем функцию waitpidв цикле, получая состояние любого из дочерних процессов, которые завершились. Необходимо задать параметр WNOHANG: это указывает функции waitpid, что не нужно блокироваться, если существуют выполняемые дочерние процессы, которые еще не завершились. В листинге 5.6 мы не могли вызвать функцию waitв цикле, поскольку нет возможности предотвратить блокирование функции waitпри наличии выполняемых дочерних процессов, которые еще не завершились.

В листинге 5.9 показана окончательная версия нашего сервера. Он корректно обрабатывает возвращение ошибки EINTRиз функции acceptи устанавливает обработчик сигнала (листинг 5.8), который вызывает функцию waitpidдля всех завершенных дочерних процессов.

Листинг 5.8. Окончательная (корректная) версия функции sig_chld, вызывающая функцию waitpid

//tcpcliserv/sigchldwaitpid.c

1 #include "unp.h"

2 void

3 sig_chld(int signo)

4 {

5 pid_t pid;

6 int stat;

7 while ((pid = waitpid(-1, &stat, WNOHANG)) >0)

8 printf("child %d terminated\n", pid);

9 return;

10 }

Листинг 5.9. Окончательная (корректная) версия TCP-сервера, обрабатывающего ошибку EINTR функции accept

//tcpcliserv/tcpserv04.c

1 #include "unp.h"

2 int

3 main(int argc, char **argv)

4 {

5 int listenfd, connfd;

6 pid_t childpid;

7 socklen_t clilen;

8 struct sockaddr_in cliaddr, servaddr;

9 void sig_chld(int);

10 listenfd = Socket(AF_INET, SOCK_STREAM, 0);

11 bzero(&servaddr, sizeof(servaddr));

12 servaddr.sin_family = AF_INET;

13 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

14 servaddr.sin_port = htons(SERV_PORT);

15 Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));

16 Listen(listenfd, LISTENQ);

17 Signal(SIGCHLD, sig_chld); /* нужно вызвать waitpid() */

18 for (;;) {

19 clilen = sizeof(cliaddr);

20 if ((connfd = accept(listenfd, (SA*)&cliaddr, &clilen)) < 0) {

21 if (errno == EINTR)

22 continue; /* назад к for() */

23 else

24 err_sys("accept error");

25 }

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

27 Close(listenfd); /* закрываем прослушиваемый сокет */

28 str_echo(connfd); /* обрабатываем запрос */

29 exit(0);

30 }

31 Close(connfd); /* родитель закрывает присоединенный сокет */

32 }

33 }

Целью этого раздела было продемонстрировать три сценария, которые могут встретиться в сетевом программировании.

1. При выполнении функции fork, порождающей дочерние процессы, следует перехватывать сигнал SIGCHLD.

2. При перехватывании сигналов мы должны обрабатывать прерванные системные вызовы.

3. Обработчик сигналов SIGCHLDдолжен быть создан корректно с использованием функции waitpid, чтобы не допустить появления зомби.

Окончательная версия нашего сервера TCP (см. листинг 5.9) вместе с обработчиком сигналов SIGCHLDв листинге 5.8 обрабатывает все три сценария.

5.11. Прерывание соединения перед завершением функции accept

Существует другое условие, аналогичное прерванному системному вызову, пример которого был описан в предыдущем разделе. Оно может привести к возвращению функцией acceptнефатальной ошибки, в случае чего следует заново вызвать функцию accept. Последовательность пакетов, показанная на рис. 5.4, встречается на загруженных серверах (эта последовательность типична для загруженных веб-серверов).

Рис 54 Получение сегмента RST для состояния соединения ESTABLISHED перед - фото 42

Рис. 5.4. Получение сегмента RST для состояния соединения ESTABLISHED перед вызовом функции accept

Трехэтапное рукопожатие TCP завершается, устанавливается соединение, а затем TCP клиента посылает сегмент RST. На стороне сервера соединение ставится в очередь в ожидании вызова функции accept, и в это время сервер получает сегмент RST. Спустя некоторое время процесс сервера вызывает функцию accept.

К сожалению, принцип обработки прерванного соединения зависит от реализации. Реализации, происходящие от Беркли, обрабатывают прерванное соединение полностью внутри ядра, и сервер никогда не узнает об этом. Большинство реализаций SVR4, однако, возвращают процессу ошибку, и эта ошибка зависит от реализации. При этом переменная errno принимает значение EPROTO(ошибка протокола), хотя в POSIX указано, что должна возвращаться ошибка ECONNABORTED(прерывание соединения). POSIX определяет эту ошибку иначе, так как ошибка EPROTOвозвращается еще и в том случае, когда в подсистеме потоков происходят какие-либо фатальные события, имеющие отношение к протоколу. Возвращение той же ошибки для нефатального прерывания установленного соединения клиентом приводит к тому, что сервер не знает, вызывать снова функцию acceptили нет. В случае ошибки ECONNABORTEDсервер может игнорировать ошибку и снова вызывать функцию accept.

ПРИМЕЧАНИЕ

Этот сценарий очень просто имитировать. Запустите сервер, который должен вызвать функции socket, bind и listen, а затем перед вызовом функции accept переведите сервер на короткое время в состояние ожидания. Пока процесс сервера находится в состоянии ожидания, запустите клиент, который вызовет функции socket и connect. Как только функция connect завершится, установите параметр сокета SO_LINGER, чтобы сгенерировать сегмент RST (который мы описываем в разделе 7.5 и демонстрируем в листинге 16.14), и завершите процессы.

ПРИМЕЧАНИЕ

В [128] описана обработка этой ошибки в Беркли-ядрах (Berkeley-derived kernels), которые никогда не передают ее процессу. Обработка RST с вызовом функции tcp_close представлена в [128, с. 964]. Эта функция вызывает функцию in_pcbdetach [128, с. 897], которая, в свою очередь, вызывает функцию sofree [128, с. 719]. Функция sofree [128, с. 473] обнаруживает, что сокет все еще находится в очереди полностью установленных соединений прослушиваемого сокета. Она удаляет этот сокет из очереди и освобождает сокет. Когда сервер, наконец, вызовет функцию accept, он не сможет узнать, что установленное соединение было удалено из очереди.

Мы вернемся к подобным прерванным соединениям в разделе 16.6 и покажем, какие проблемы они могут порождать совместно с функцией selectи прослушиваемым сокетом в нормальном режиме блокирования.

5.12. Завершение процесса сервера

Теперь мы запустим соединение клиент-сервер и уничтожим дочерний процесс сервера. Это симулирует сбой процесса сервера, благодаря чему мы сможем выяснить, что происходит с клиентом в подобных ситуациях. (Следует точно различать сбой процесса сервера, который мы рассмотрим здесь, и сбой на самом узле сервера, о котором речь пойдет в разделе 5.14.) События развиваются так:

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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