UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
str_cli: server terminated prematurelyКогда мы вводим следующую строку, функция
str_cliwritenКогда TCP сервера получает данные от клиента, он отвечает сегментом RST, поскольку процесс, у которого был открытый сокет, завершился. Мы можем проверить, что этот сегмент RST отправлен, просмотрев пакеты с помощью программы
tcpdump7. Однако процесс клиента не увидит сегмента RST, поскольку он вызывает функцию
readlinewritenreadlineServer terminated prematurelyЭтапы описанной последовательности также зависят от синхронизации времени. Вызов readline на стороне клиента может произойти до получения им пакета RST от сервера, но может произойти и после. Если readline вызывается до получения RST, происходит то, что мы описали выше (клиент считывает символ конца файла). Если же первым будет получен пакет RST, функция readline возвратит ошибку ECONNRESET (соединение сброшено собеседником).
8. Когда клиент завершает работу (вызывая функцию
err_quitПроблема заключается в том, что клиент блокируется в вызове функции
fgetsstr_cliselectpollstr_clikill5.13. Сигнал SIGPIPE
Что происходит, если клиент игнорирует возвращение ошибки из функции
readlineПрименяется следующее правило: когда процесс производит запись в сокет, получивший сегмент RST, процессу посылается сигнал
SIGPIPEЕсли процесс либо перехватывает сигнал и возвращается из обработчика сигнала, либо игнорирует сигнал, то операция записи возвращает ошибку
EPIPEЧасто задаваемым вопросом (FAQ) в Usenet является такой: как получить этот сигнал при первой, а не при второй операции записи? Это невозможно. Как следует из приведенных выше рассуждений, первая операция записи выявляет сегмент RST, а вторая — сигнал. Если запись в сокет, получивший сегмент FIN, допускается, то запись в сокет, получивший сегмент RST, является ошибочной.
Чтобы увидеть, что происходит с сигналом
SIGPIPEЛистинг 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-9writenwritenSIGPIPEЕсли мы запустим клиент на нашем узле Linux, мы получим:
linux % <b>tcpcli11 127.0.0.1</b><b>hi there</b> <i>мы вводим эту строку</i>hi there <i>и она отражается сервером</i><i>здесь мы завершаем дочерний процесс сервера</i><b>bye</b> <i>затем мы вводим эту строку</i>Broken pipe <i>это сообщение выводится интерпретатором</i>Мы запускаем клиент, вводим одну строку, видим, что строка отражена корректно, и затем завершаем дочерний процесс сервера на узле сервера. Затем мы вводим другую строку (
byebashРекомендуемый способ обработки сигнала
SIGPIPESIG_IGNEPIPEwriteEPIPEwrite
