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 else
13 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 void
23 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-20
accept
SIGURG
pause
22-31
recv
Если мы запускаем сначала принимающую программу, а затем программу отправки, то получаем следующий результат выполнения программы отправки:
macosx % <b>tcpsend05 freebsd 5555</b>
wrote 16384 bytes of normal data
wrote 1 byte of OOB data
wrote 1024 bytes of normal data
Как и ожидалось, все данные помещаются в буфер отправки сокета отправителя, и программа завершается. Ниже приведен результат работы принимающей программы:
freebsd4 % <b>tcprecv05 5555</b>
SIGURG received
recv error: Resource temporarily unavailable
Сообщение об ошибке, которое выдает наша функция
err_sys
EAGAIN
EWOULDBLOCK
SIGURG
recv
MSG_OOB
Для решения этой проблемы необходимо, чтобы получатель освобождал место в своем приемном буфере, считывая поступившие обычные данные. В результате TCP объявит для отправителя окно ненулевого размера, что в конечном счете позволит отправителю передать байт, содержащий внеполосные данные.
В реализациях, происходящих от Беркли [128, с. 1016-1017], можно отметить две близких проблемы. Во-первых, даже если приемный буфер сокета заполнен, ядро всегда принимает от процесса внеполосные данные для отправки собеседнику. Во-вторых, когда отправитель посылает байт с внеполосными данными, немедленно посылается сегмент TCP, содержащий срочное уведомление. Все обычные проверки вывода TCP (алгоритм Нагла, предотвращение синдрома «глупого окна») при этом блокируются.
Пример: единственность отметки внеполосных данных в TCP
Нашим очередным примером мы иллюстрируем тот факт, что для данного соединения TCP существует всего одна отметка внеполосных данных, и если новые внеполосные данные прибудут прежде, чем принимающий процесс начнет считывать пришедшие ранее внеполосные данные, то предыдущая отметка будет утеряна.
В листинге 24.10 показана посылающая программа, аналогичная программе, приведенной в листинге 24.6. Отличие заключается в том, что сейчас мы добавили еще одну функцию
send
write
Листинг 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#>");