24.1. Да, разница есть. В первом примере два байта отсылаются с единственным срочным указателем, который указывает на байт, следующий за b
. Во втором же примере (вызываются две функции) сначала отсылается символ a
с указателем срочности, который указывает на следующий за ним байт, а за этим сегментом следует еще один TCP-сегмент, содержащий символ b
с другим указателем срочности, указывающим на следующий за ним байт.
24.2. В листинге Д.10 приведена версия программы с использованием функции poll
.
Листинг Д.10. Версия программы из листинга 24.4, использующая функцию poll вместо функции select
//oob/tcprecv03p.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int listenfd, connfd, n, justreadoob = 0;
6 char buff[100];
7 struct pollfd pollfd[1];
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: tcprecv03p [
14 connfd = Accept(listenfd, NULL, NULL);
15 pollfd[0].fd = connfd;
16 pollfd[0].events = POLLRDNORM;
17 for (;;) {
18 if (justreadoob == 0)
19 pollfd[0].events |= POLLRDBAND;
20 Poll(pollfd, 1, INFTIM);
21 if (pollfd[0].revents & POLLRDBAND) {
22 n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);
23 buff[n] = 0; /* завершающий нуль */
24 printf("read %d OOB byte: %s\n", n, buff);
25 justreadoob = 1;
26 pollfd[0].events &= ~POLLRDBAND; /* отключение бита */
27 }
28 if (pollfd[0].revents & POLLRDNORM) {
29 if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {
30 printf("received EOF\n");
31 exit(0);
32 }
33 buff[n] = 0; /* завершающий нуль */
34 printf("read %d bytes %s\n", n, buff);
35 justreadoob = 0;
36 }
37 }
38 }
Глава 25
25.1. Нет, такая модификация приведет к ошибке. Проблема состоит в том, что nqueue
уменьшается до того, как завершается обработка элемента массива dg[iget]
, что позволяет обработчику сигналов считывать новую дейтаграмму в данный элемент массива.
Глава 26
26.1. В примере с функцией fork
будет использоваться 101 дескриптор, один прослушиваемый сокет и 100 присоединенных сокетов. Но каждый из 101 процесса (один родительский и 100 дочерних) имеет только один открытый дескриптор (игнорируем все остальные, такие как стандартный поток ввода, если сервер не является демоном). В случае сервера с потоками используется 101 дескриптор для одного процесса. Каждым потоком (включая основной) обрабатывается один дескриптор.
26.2. Обмена двумя последними сегментами завершения TCP-соединения (сегмент FIN сервера и сегмент ACK клиента в ответ на сегмент FIN сервера) не произойдет. Это переведет клиентский конец соединения в состояние FIN_WAIT_2 (см. рис. 2.4). Беркли-реализации прервут работу клиентского конца, если он остался в этом состоянии, по тайм-ауту через 11 минут [128, с. 825–827]. У сервера же в конце концов закончатся дескрипторы.
26.3. Это сообщение будет выводиться основным программным потоком в том случае, когда он считывает из сокета признак конца файла done
, инициализируемую нулем. Прежде чем функция copyto
программного потока вернет управление, она установит эту переменную в 1. Основной программный поток проверит эту переменную, и если она равна нулю, выведет сообщение об ошибке. Поскольку значение переменной устанавливает только один программный поток, нет необходимости в синхронизации.
Глава 27
27.1. Ничего не изменится. Все системы являются соседями, поэтому гибкая маршрутизация идентична жесткой.
27.2. Мы бы поместили EOL (нулевой байт) в конец буфера.
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии