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 и более ранние версии) всегда возвращают нулевой размер буфера сокета, не давая нам возможности увидеть, что происходит с этим значением в процессе соединения.
До вызова функции
connectconnecttcpdumpМногие реализации после установления соединения округляют размер приемного буфера сокета в большую сторону, чтобы он было кратным MSS. Чтобы узнать размер приемного буфера сокета после установления соединения, можно исследовать пакеты с помощью программы типа
tcpdump7.3. Разместите в памяти структуру
lingerlingstr_cli(stdin, sockfd);ling.l_onoff = 1;ling.l_linger = 0;Setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));exit(0);Это заставит TCP на стороне клиента прекратить работу путем отправки сегмента RST вместо нормального обмена четырьмя сегментами. Дочерний процесс сервера вызывает функцию
readlineECONNRESETreadline error: Connection reset by peerКлиентский сокет не должен проходить через состояние ожидания TIME_WAIT, даже если клиент выполняет активное закрытие.
7.4. Первый клиент вызывает функции
setsockoptbindconnectbindbindconnectEADDRINUSEbindEADDRINUSEbind7.5. Запускаем программу на узле без поддержки многоадресной передачи (MacOS X 10.2.6).
macosx % <b>sock -s 9999 &</b> <i>запускаем первый сервер с универсальным адресом</i>[1] 29697macosx % <b>sock -s 172.24.37.78 9999</b> <i>пробуем второй сервер, но без -А</i>can't bind local address: Address already in usemacosx % <b>sock -s -A 172.24.37.78 9999 &</b> <i>пробуем опять с -A: работает</i>[2] 29699macosx % <b>sock -s -A 127.0.0.1 9999 &</b> <i>третий сервер с -A; работает</i>[3] 29700macosx % <b>netstat -na | grep 9999</b>tcp4 0 0 127.0.0.1.9999 *.* LISTENtcp4 0 0 206.62.226.37.9999 *.* LISTENtcp4 0 0 *.9999 *.* LISTEN7.6. Теперь попробуем проделать то же на узле с поддержкой многоадресной передачи, но без поддержки параметра
SO_REUSEADDR
