UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Листинг Д.2. Вывод размера приемного буфера сокета и MSS до и после установления соединения
//sockopt/rcvbuf.c
1 #include "urp.h"
2 #include <netinet/tcp.h> /* для TCP_MAXSEG */
3 int
4 main(int argc, char **argv)
5 {
6 int sockfd, rcvbuf, mss;
7 socklen_t len;
8 struct sockaddr_in servaddr;
9 if (argc != 2)
10 err_quit("usage: rcvbuf <Ipaddress>");
11 sockfd = Socket(AF_INET, SOCK_STREAM, 0);
12 len = sizeof(rcvbuf);
13 Getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len);
14 len = sizeof(mss);
15 Getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len);
16 printf("defaults: SO_RCVBUF = %d. MSS = %dn", rcvbuf, mss);
17 bzero(&servaddr, sizeof(servaddr));
18 servaddr.sin_family = AF_INET;
19 servaddr.sin_port = htons(13); /* сервер времени и даты */
20 Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
21 Connect(sockfd, (SA*)&servaddr, sizeof(servaddr));
22 len = sizeof(rcvbuf);
23 Getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len);
24 len = sizeof(mss);
25 Getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len);
26 printf("after connect: SO_RCVBUF = %d, MSS = %dn", rcvbuf, mss);
27 exit(0);
28 }
He существует какого-то одного «правильного» вывода для данной программы. Результаты зависят от системы. Некоторые системы (в особенности Solaris 2.5.1 и более ранние версии) всегда возвращают нулевой размер буфера сокета, не давая нам возможности увидеть, что происходит с этим значением в процессе соединения.
До вызова функции
connect
connect
tcpdump
Многие реализации после установления соединения округляют размер приемного буфера сокета в большую сторону, чтобы он было кратным MSS. Чтобы узнать размер приемного буфера сокета после установления соединения, можно исследовать пакеты с помощью программы типа
tcpdump
7.3. Разместите в памяти структуру
linger
ling
str_cli(stdin, sockfd);
ling.l_onoff = 1;
ling.l_linger = 0;
Setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
exit(0);
Это заставит TCP на стороне клиента прекратить работу путем отправки сегмента RST вместо нормального обмена четырьмя сегментами. Дочерний процесс сервера вызывает функцию
readline
ECONNRESET
readline error: Connection reset by peer
Клиентский сокет не должен проходить через состояние ожидания TIME_WAIT, даже если клиент выполняет активное закрытие.
7.4. Первый клиент вызывает функции
setsockopt
bind
connect
bind
bind
connect
EADDRINUSE
bind
EADDRINUSE
bind
7.5. Запускаем программу на узле без поддержки многоадресной передачи (MacOS X 10.2.6).
macosx % <b>sock -s 9999 &</b> <i>запускаем первый сервер с универсальным адресом</i>
[1] 29697
macosx % <b>sock -s 172.24.37.78 9999</b> <i>пробуем второй сервер, но без -А</i>
can't bind local address: Address already in use
macosx % <b>sock -s -A 172.24.37.78 9999 &</b> <i>пробуем опять с -A: работает</i>
[2] 29699
macosx % <b>sock -s -A 127.0.0.1 9999 &</b> <i>третий сервер с -A; работает</i>
[3] 29700
macosx % <b>netstat -na | grep 9999</b>
tcp4 0 0 127.0.0.1.9999 *.* LISTEN
tcp4 0 0 206.62.226.37.9999 *.* LISTEN
tcp4 0 0 *.9999 *.* LISTEN
7.6. Теперь попробуем проделать то же на узле с поддержкой многоадресной передачи, но без поддержки параметра
SO_REUSEADDR