UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
20 sleep(1);
21 Write(sockfd, "89", 2);
22 printf("wrote 2 bytes of normal datan");
23 sleep(1);
24 exit(0);
25 }
Отправлены 9 байт, промежуток между операциями по отправке установлен с помощью функции
sleep
write
send
macosx % <b>tcpsend01 freebsd 9999</b>
wrote 3 bytes of normal data
wrote 1 byte of OOB data
wrote 2 bytes of normal data
wrote 1 byte of OOB data
wrote 2 bytes of normal data
В листинге 24.2 показана принимающая программа.
Листинг 24.2. Простая программа для получения внеполосных данных
//oob/tcprecv01.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 n;
8 char buff[100];
9 if (argc == 2)
10 listenfd = Tcp_listen(NULL, argv[1], NULL);
11 else if (argc == 3)
12 listenfd = Tcp_listen(argv[1], argv[2], NULL);
13 else
14 err_quit("usage: tcprecv01 [ <host> ] <port#>");
15 connfd = Accept(listenfd, NULL, NULL);
16 Signal(SIGURG, sig_urg);
17 Fcntl(connfd, F_SETOWN, getpid());
18 for (;;) {
19 if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {
20 printf("received EOFn");
21 exit(0);
22 }
23 buff[n] = 0; /* завершающий нуль */
24 printf("read bytes: %sn", n, buff);
25 }
26 }
27 void
28 sig_urg(int signo)
29 {
30 int n;
31 char buff[100];
32 printf("SIGURG receivedn");
33 n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);
34 buff[n] = 0; /* завершающий нуль */
35 printf("read OOB byte: %sn", n, buff);
36 }
16-17
SIGURG
fcntl
Обратите внимание, что мы не задаем обработчик сигнала, пока не завершается функция accept. Существует небольшая вероятность того, что внеполосные данные могут прибыть после того, как TCP завершит трехэтапное рукопожатие, но до завершения функции accept. Внеполосные данные мы в этом случае потеряем. Допустим, что мы установили обработчик сигнала перед вызовом функции accept, а также задали владельца прослушиваемого сокета (который затем стал бы владельцем присоединенного сокета). Тогда, если внеполосные данные прибудут до завершения функции accept, наш обработчик сигналов еще не получит значения для дескриптора connfd. Если данный сценарий важен для приложения, следует инициализировать connfd, «вручную» присвоив этому дескриптору значение -1, добавить в обработчик проверку равенства connfd ==-1 и при истинности этого условия просто установить флаг, который будет проверяться в главном цикле после вызова accept. За счет этого главный цикл сможет узнать о поступлении внеполосных данных и считать их. Можно заблокировать сигнал на время вызова accept, но при этом программа будет страдать от всех возможных ситуаций гонок, описанных в разделе 20.5.
18-25
read
27-36
printf
MSG_OOB
Как сказано ранее, вызов ненадежной функции printf из обработчика сигнала не рекомендуется. Мы делаем это просто для того, чтобы увидеть, что произойдет с нашей программой.
Ниже приведен результат, который получается, когда мы запускаем эту программу, а затем — программу для отправки внеполосных данных, приведенную в листинге 24.1.
freebsd % <b>tcprecv01 9999</b>
read 3 bytes: 123
SIGURG received
read 1 OOB byte: 4
read 2 bytes: 56
SIGURG received
read 1 OOB byte: 7