Уильям Стивенс - 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. Мы запускаем сервер и клиент на разных узлах и вводим на стороне клиента одну строку, чтобы проверить, все ли в порядке. Строка отражается дочерним процессом сервера.

2. Мы находим идентификатор дочернего процесса сервера и уничтожаем его с помощью программы kill. Одним из этапов завершения процесса является закрытие всех открытых дескрипторов в дочернем процессе. Это вызывает отправку сегмента FIN клиенту, и TCP клиента отвечает сегментом ACK. Это первая половина завершения соединения TCP.

3. Родительскому процессу сервера посылается сигнал SIGCHLD, и он корректно обрабатывается (см. листинг 5.9).

4. С клиентом ничего не происходит. TCP клиента получает от TCP сервера сегмент FIN и отвечает сегментом ACK, но проблема состоит в том, что клиентский процесс блокирован в вызове функции fgetsв ожидании строки от терминала.

5. Запуск программы netstatна этом шаге из другого окна на стороне клиента показывает состояние клиентского сокета:

linux % netstat -a | grep 9877

tcp 0 0 *:9877 *:* LISTEN

tcp 0 0 localhost:9877 localhost:9877 FIN_WAIT2

tcp 1 0 localhost.43604 localhost:9877 CLOSE_WAIT

Как видите, согласно рис. 2.4, осуществилась половина последовательности завершения соединения TCP.

6. Мы можем снова ввести строку на стороне клиента. Вот что происходит на стороне клиента (начиная с шага 1):

linux % tcpcli01 127.0.0.1 запускаем клиент

hello первая строка, которую мы ввели

hello она корректно отражается

теперь мы уничтожаем ( kill ) дочерний процесс

сервера на узле сервера

another line затем мы вводим следующую строку на стороне клиента

str_cli: server terminated prematurely

Когда мы вводим следующую строку, функция str_cliвызывает функцию writen, и TCP клиента отправляет данные серверу. TCP это допускает, поскольку получение сегмента FIN протоколом TCP клиента указывает только на то, что процесс сервера закрыл свой конец соединения и больше не будет отправлять данные. Получение сегмента FIN не сообщает протоколу TCP клиента, что процесс сервера завершился (хотя в данном случае он завершился). Мы вернемся к этому вопросу в разделе 6.6, когда будем говорить о половинном закрытии TCP.

Когда TCP сервера получает данные от клиента, он отвечает сегментом RST, поскольку процесс, у которого был открытый сокет, завершился. Мы можем проверить, что этот сегмент RST отправлен, просмотрев пакеты с помощью программы tcpdump.

7. Однако процесс клиента не увидит сегмента RST, поскольку он вызывает функцию readlineсразу же после вызова функции writen, и readlineсразу же возвращает 0 (признак конца файла) по причине того, что на шаге 2 был получен сегмент FIN. Наш клиент не предполагает получать признак конца файла на этом этапе (см. листинг 5.3), поэтому он завершает работу, сообщая об ошибке Server terminated prematurely(Сервер завершил работу преждевременно).

ПРИМЕЧАНИЕ

Этапы описанной последовательности также зависят от синхронизации времени. Вызов readline на стороне клиента может произойти до получения им пакета RST от сервера, но может произойти и после. Если readline вызывается до получения RST, происходит то, что мы описали выше (клиент считывает символ конца файла). Если же первым будет получен пакет RST, функция readline возвратит ошибку ECONNRESET (соединение сброшено собеседником).

8. Когда клиент завершает работу (вызывая функцию err_quitв листинге 5.4), все его открытые дескрипторы закрываются.

Проблема заключается в том, что клиент блокируется в вызове функции fgets, когда сегмент FIN приходит на сокет. Клиент в действительности работает с двумя дескрипторами — дескриптором сокета и дескриптором ввода пользователя, и поэтому он должен блокироваться при вводе из любого источника (сейчас в функции str_cliон блокируется при вводе только из одного источника). Обеспечить подобное блокирование — это одно из назначений функций selectи poll, о которых рассказывается в главе 6. Когда в разделе 6.4 мы перепишем функцию str_cli, то как только мы уничтожим с помощью программы killдочерний процесс сервера, клиенту будет отправлено уведомление о полученном сегменте FIN.

5.13. Сигнал SIGPIPE

Что происходит, если клиент игнорирует возвращение ошибки из функции readlineи отсылает следующие данные серверу? Это может произойти, если, например, клиенту нужно выполнить две операции по отправке данных серверу перед считыванием данных от него, причем первая операция отправки данных вызывает RST.

Применяется следующее правило: когда процесс производит запись в сокет, получивший сегмент RST, процессу посылается сигнал SIGPIPE. По умолчанию действием этого сигнала является завершение процесса, так что процесс должен перехватить сигнал, чтобы не произошло непроизвольного завершения.

Если процесс либо перехватывает сигнал и возвращается из обработчика сигнала, либо игнорирует сигнал, то операция записи возвращает ошибку EPIPE.

ПРИМЕЧАНИЕ

Часто задаваемым вопросом (FAQ) в Usenet является такой: как получить этот сигнал при первой, а не при второй операции записи? Это невозможно. Как следует из приведенных выше рассуждений, первая операция записи выявляет сегмент RST, а вторая — сигнал. Если запись в сокет, получивший сегмент FIN, допускается, то запись в сокет, получивший сегмент RST, является ошибочной.

Чтобы увидеть, что происходит с сигналом SIGPIPE, изменим код нашего клиента так, как показано в листинге 5.10.

Листинг 5.10. Функция str_cli, дважды вызывающая функцию writen

//tcpcliserv/str_cli11.c

1 #include "unp.h"

2 void

3 str_cli(FILE *fp, int sockfd)

4 {

5 char sendline[MAXLINE], recvline[MAXLINE];

6 while (Fgets(sendline, MAXLINE, fp) != NULL) {

7 Writen(sockfd, sendline, 1);

8 sleep(1);

9 Writen(sockfd, sendline + 1, strlen(sendline) - 1);

10 if (Readline(sockfd, recvline, MAXLINE) == 0)

11 err_quit("str_cli, server terminated prematurely");

12 Fputs(recvline, stdout);

13 }

14 }

7-9 Все изменения, которые мы внесли, — это повторный вызов функции writen: сначала в сокет записывается первый байт данных, за этим следует пауза в 1 с и далее идет запись остатка строки. Наша цель — выявить сегмент RST при первом вызове функции writenи генерировать сигнал SIGPIPEпри втором вызове.

Если мы запустим клиент на нашем узле Linux, мы получим:

linux % tcpcli11 127.0.0.1

hi there мы вводим эту строку

hi there и она отражается сервером

здесь мы завершаем дочерний процесс сервера

bye затем мы вводим эту строку

Broken pipe это сообщение выводится интерпретатором

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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