UNIX: разработка сетевых приложений, стр. 393
35 void
36 do_parent(void)
27 {
38 int backlog, j, k, junk, fd[MAXBACKLOG + 1];
39 Close(cfd);
40 Signal(SIGALRM, parent_alrm);
41 for (backlog = 0; backlog <= 14; backlogs) {
42 printf("backlog = %d. ", backlog);
43 Write(pfd, &backlog. sizeof(int)); /* сообщение значения дочернему процессу */
44 Read(pfd, &junk, sizeof(int)); /* ожидание дочернего процесса */
45 for (j = 1; j <= MAXBACKLOG; j++) {
46 fd[j] = Socket(AF_INET, SOCK_STREAM, 0);
47 alarm(2);
48 if (connect(fd[j], (SA*)&serv, sizeof(serv)) < 0) {
49 if (errno != EINTR)
50 err_sys("connect error, j = %d", j);
51 printf("timeout, %d connections completed\n", j - 1);
52 for (k = 1; k <= j; k++)
53 Close(fd[k]);
54 break; /* следующее значение backlog */
55 }
56 alarm(0);
57 }
58 if (j > MAXBACKLOG)
59 printf("Id connections?\n", MAXBACKLOG);
60 }
61 backlog = -1; /* сообщаем дочернему процессу, что все сделано */
62 Write(pfd, &backlog, sizeof(int));
63 }
64 void
65 do_child(void)
66 {
67 int listenfd, backlog, junk;
68 const int on = 1;
69 Close(pfd);
70 Read(cfd, &backlog, sizeof(int)); /* ожидание родительского процесса */
71 while (backlog >= 0) {
72 listenfd = Socket(AF_NET, SOCK_STREAM, 0);
73 Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
74 Bind(listenfd, (SA*)&serv, sizeof(serv));
75 Listen(listenfd, backlog); /* начало прослушивания */
76 Write(cfd, &junk, sizeof(int)); /* сообщение родительскому процессу */
77 Read(cfd, &backlog, sizeof(int)); /* ожидание родительского процесса */
78 Close(listenfd); /* также закрывает все соединения в очереди */
79 }
80 }
Глава 16
16.1. Дескриптор используется совместно родительским и дочерним процессами, поэтому его счетчик ссылок равен 2. Если родительский процесс вызывает функцию
close
shutdown
16.2. Родительский процесс продолжит запись в сокет, получивший сегмент FIN, а первый сегмент, посланный серверу, вызовет получение сегмента RST в ответ. После этого функция
write
SIGPIPE
16.3. Когда дочерний процесс вызывает функцию
getppid
SIGTERM
init
init
init
getppid
16.4. Если удалить эти две строки, вызывается функция
select
select
goto
select
16.5. Это может случиться, если сервер отправляет данные сразу, как только завершается его функция
accept
Глава 17
17.1. Нет, это не имеет значения, поскольку первые три элемента объединения в листинге 17.1 являются структурами адреса сокета.
Глава 18
18.1. Элемент
sdl_nlen
sdl_alen
18.2. На этот сокет никогда не посылается ответ от ядра. Данный параметр сокета (
SO_USELOOPBACK
Глава 20
20.1. Если вы получаете большое количество ответов, они могут следовать каждый раз в разном порядке. Правда, отправляющий узел обычно выводится первым, поскольку дейтаграммы, направленные к нему или от него, не появляются в реальной сети.