UNIX: разработка сетевых приложений
Шрифт:
exit(main(argc, argv));
Следовательно, вызывается функция
exit
, а затем и программа очистки стандартного ввода-вывода. Глава 15
15.1. Функция
unlink
удаляет имя файла из файловой системы, и когда клиент позже вызовет функцию connect
, она не выполнится. Это не влияет на прослушиваемый сокет сервера, но клиенты не смогут выполнить функции connect
после вызова функции unlink
. 15.2. Клиент не сможет соединиться с сервером с помощью функции
connect
, даже если полное имя
connect
доменный сокет Unix должен быть открыт и связан с этим полным именем (см. раздел 15.4). 15.3. При выводе адреса протокола клиента путем вызова функции
sock_ntop
мы получим сообщение datagram from (no pathname bound)
(дейтаграмма от (имя не задано)), поскольку по умолчанию с сокетом клиента не связывается никакое имя. Одним из решений является проверить доменный сокет Unix в функциях
udp_client
и udp_connect
и связать с сокетом при помощи функции bind
временное полное имя. Это приведет к зависимости от протокола в библиотечной функции, но не в нашем приложении. 15.4. Даже если мы заставим сервер вернуть в функции
write
1 байт на его 26- байтовый ответ, использование функции sleep
на стороне клиента гарантирует, что все 26 сегментов будут получены до вызова функции read
, в результате чего функция read
вернет полный ответ. Это еще одно подтверждение того, что TCP является потоком байтов с отсутствием границ записей. Чтобы использовать доменные протоколы Unix, запускаем клиент и сервер с двумя аргументами командной строки
/lосаl
(или /unix
) и /tmp/daytime
(или любое другое временное имя, которое вы хотите использовать). Ничего не изменится: 26 байт будут возвращаться функцией read
каждый раз, когда будет запускаться клиент. Поскольку для каждой функции
send
сервер определяет флаг MSG_EOR
, каждый байт рассматривается как логическая запись, и функция read
при каждом вызове возвращает 1 байт. Причина в том, что Беркли-реализации поддерживают флаг MSG_EOR
по умолчанию. Однако этот факт не документирован и не может использоваться в серийном коде. В данном примере мы используем эту особенность, чтобы показать разницу между потоком байтов и ориентированным на записи протоколом. С точки зрения реализации, каждая операция вывода идет в mbuf
(буфер памяти) и флаг MSG_EOR
сохраняется ядром вместе с mbuf
, когда mbuf
переходит из отправляющего сокета в приемный буфер принимающего сокета. Когда вызывается функция read, флаг MSG_EOR
все еще присоединен к каждому mbuf
, так что основная подпрограмма ядра read
(поддерживающая флаг MSG_EOR
, поскольку некоторые протоколы используют этот флаг) сама возвращает каждый байт. Если бы вместо read
мы использовали recvmsg
, флаг MSG_EOR
возвращался бы в поле msg_flags
каждый раз, когда recvmsg
возвращала бы 1 байт. Такой подход в TCP не срабатывает, поскольку отправляющий TCP не анализирует флаг MSG_EOR
в отсылаемом mbuf
и в любом случае у нас нет возможности передать этот флаг принимающему TCP в TCP-заголовке. (Выражаем благодарность Мату Томасу (Matt Thomas) за то, что он указал нам это недокументированное «средство».) 15.5. В листинге Д.7 приведена реализация данной программы.
Листинг Д.7. Определение фактического количества собранных в очередь соединений для различных значений аргумента backlog
//debug//backlog.c
1 #include "unp.h"
2 #define PORT 9999
3 #define ADDR "127 0.0.1"
4 #define MAXBACKLOG 100
5 /* глобальные переменные */
6 struct sockaddr_in serv;
7 pid_t pid; /* дочерний процесс */
8 int pipefd[2];
9 #define pfd pipefd[1] /* сокет родительского процесса */
10 #define cfd pipefd[0] /* сокет дочернего процесса */
11 /* прототипы функций */
12 void do_parent(void);
13 void do_child(void);
14 int
15 main(int argc, char **argv)
16 {
17 if (argc != 1)
18 err_quit("usage: backlog");
19 Socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd);
20 bzero(&serv, sizeof(serv));
21 serv.sin_family = AF_INET;
22 serv.sin_port = htons(PORT);
23 Inet_pton(AF_INET, ADDR, &serv.sin_addr);
24 if ((pid = Fork) == 0)
25 do_child;
26 else
27 do_parent;
28 exit(0);
29 }
30 void
31 parent_alrm(int signo)
32 {
33 return; /* прерывание блокированной функции connect */
34 }
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) {
Поделиться:
Популярные книги
Диверсант
2. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Измена. Осколки чувств
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Солдат Империи
1. Страж
Фантастика:
попаданцы
альтернативная история
6.67
рейтинг книги
Ваше Сиятельство 4т
4. Ваше Сиятельство
Любовные романы:
эро литература
5.00
рейтинг книги
Идеальный мир для Социопата 3
3. Социопат
Фантастика:
боевая фантастика
6.17
рейтинг книги
Темный Патриарх Светлого Рода
1. Темный Патриарх Светлого Рода
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Рождение победителя
3. Девятый
Фантастика:
фэнтези
альтернативная история
9.07
рейтинг книги
Последний Паладин. Том 6
6. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 8
8. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Курсант: Назад в СССР 11
11. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Замуж второй раз, или Ещё посмотрим, кто из нас попал!
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Мне нужна жена
Любовные романы:
современные любовные романы
6.88
рейтинг книги
Темный Патриарх Светлого Рода 2
2. Темный Патриарх Светлого Рода
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Большие дела
7. Цеховик
Фантастика:
попаданцы
альтернативная история
5.00