UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
19 exit(0);20 }9-19В листинге 24.9 представлена принимающая программа.
Листинг 24.9. Принимающая программа
//oob/tcprecv05.c 1 #include "unp.h" 2 int listenfd, connfd; 3 void sig_urg(int); 4 int 5 main(int argc, char **argv) 6 { 7 int size; 8 if (argc == 2) 9 listenfd = Tcp_listen(NULL, argv[1], NULL);10 else if (argc == 3)11 listenfd = Tcp_listen(argv[1], argv[2], NULL);12 else13 err_quit("usage: tcprecv05 [ <host> ] <port#>");14 size = 4096;15 Setsockopt(listenfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));16 connfd = Accept(listenfd, NULL, NULL);17 Signal(SIGURG, sig_urg);18 Fcntl(connfd, F_SETOWN, getpid());19 for (;;)20 pause();21 }22 void23 sig_urg(int signo)24 {25 int n;26 char buff[2048];27 printf("SIGURG receivedn");28 n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);29 buff[n] = 0; /* завершающий пустой байт */30 printf("read %d OOB byten", n);31 }14-20acceptSIGURGpause22-31recvЕсли мы запускаем сначала принимающую программу, а затем программу отправки, то получаем следующий результат выполнения программы отправки:
macosx % <b>tcpsend05 freebsd 5555</b>wrote 16384 bytes of normal datawrote 1 byte of OOB datawrote 1024 bytes of normal dataКак и ожидалось, все данные помещаются в буфер отправки сокета отправителя, и программа завершается. Ниже приведен результат работы принимающей программы:
freebsd4 % <b>tcprecv05 5555</b>SIGURG receivedrecv error: Resource temporarily unavailableСообщение об ошибке, которое выдает наша функция
err_sysEAGAINEWOULDBLOCKSIGURGrecvMSG_OOBДля решения этой проблемы необходимо, чтобы получатель освобождал место в своем приемном буфере, считывая поступившие обычные данные. В результате TCP объявит для отправителя окно ненулевого размера, что в конечном счете позволит отправителю передать байт, содержащий внеполосные данные.
В реализациях, происходящих от Беркли [128, с. 1016-1017], можно отметить две близких проблемы. Во-первых, даже если приемный буфер сокета заполнен, ядро всегда принимает от процесса внеполосные данные для отправки собеседнику. Во-вторых, когда отправитель посылает байт с внеполосными данными, немедленно посылается сегмент TCP, содержащий срочное уведомление. Все обычные проверки вывода TCP (алгоритм Нагла, предотвращение синдрома «глупого окна») при этом блокируются.
Пример: единственность отметки внеполосных данных в TCP
Нашим очередным примером мы иллюстрируем тот факт, что для данного соединения TCP существует всего одна отметка внеполосных данных, и если новые внеполосные данные прибудут прежде, чем принимающий процесс начнет считывать пришедшие ранее внеполосные данные, то предыдущая отметка будет утеряна.
В листинге 24.10 показана посылающая программа, аналогичная программе, приведенной в листинге 24.6. Отличие заключается в том, что сейчас мы добавили еще одну функцию
sendwriteЛистинг 24.10. Отправка двух байтов внеполосных данных друг за другом
//oob/tcpsend06.c 1 #include "unp.h" 2 int 3 main(int argc, char **argv) 4 { 5 int sockfd; 6 if (argc != 3) 7 err_quit("usage: tcpsend04 <host> <port#>");
