UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Сначала мы изменяем функцию клиента
mainservaddr.sin_port = htons(SERV_PORT);присваиванием
servaddr.sin_port = htons(7);Теперь мы можем использовать с нашим клиентом любой узел, на котором работает стандартный эхо-сервер.
Затем мы переписываем функцию
dg_clirecvfromЛистинг 8.5. Версия функции dg_cli, проверяющая возвращаемый адрес сокета
//udpcliserv/dgcliaddr.c 1 #include "unp.h" 2 void 3 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) 4 { 5 int n; 6 char sendline[MAXLINE], recvline[MAXLINE + 1]; 7 socklen_t len; 8 struct sockaddr *preply_addr; 9 preply_addr = Malloc(servlen);10 while (Fgets(sendline, MAXLINE, fp) != NULL) {11 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);12 len = servlen;13 n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);14 if (len != servlen || memcmp(pservaddr, preply_addr, len) != 0) {15 printf("reply from %s (ignored)n",16 continue;17 }18 recvline[n] = 0; /* завершающий нуль */19 Fputs(recvline, stdout);20 }21 }9mallocdg_climalloc12-13recvfromrecvfrommemcmpНовая версия нашего клиента работает замечательно, если сервер находится на узле с одним единственным IP-адресом. Но эта программа может не сработать, если сервер имеет несколько сетевых интерфейсов (multihomed server). Запускаем эту программу, обращаясь к узлу
freebsd4macosx % <b>host freebsd4</b>freebsd4.unpbook.com has address 172.24.37.94freebsd4.unpbook.com has address 135.197.17.100macosx % <b>udpcli02 135.197.17.100</b><b>hello</b>reply from 172.24.37.94:7 (ignored)<b>goodbye</b>reply from 172.24.37.94:7 (ignored)По рис. 1.7 видно, что мы задали IP-адрес из другой подсети. Обычно это допустимо. Большинство реализаций IP принимают приходящую IP-дейтаграмму, предназначенную для любого из IP-адресов узла, независимо от интерфейса, на который она приходит [128, с. 217-219]. Документ RFC 1122 [10] называет это моделью системы с гибкой привязкой (weak end system model). Если система должна реализовать то, что в этом документе называется моделью системы с жесткой привязкой (strong end system model), она принимает приходящую дейтаграмму, только если дейтаграмма приходит на тот интерфейс, которому она адресована.
IP-адрес, возвращаемый функцией
recvfromfreebsd4netstatfreebsd4Одним из решений будет проверка клиентом доменного имени отвечающего узла вместо его IP-адреса. Для этого имя сервера ищется в DNS (см. главу 11) на основе IP-адреса, возвращаемого функцией
recvfrombindselectВ системе Solaris с несколькими сетевыми интерфейсами IP-адрес отправителя ответа сервера — это IP-адрес получателя клиентского запроса. Сценарий, описанный в данном разделе, относится к реализациям, происходящим от Беркли, которые выбирают IP-адрес отправителя, основываясь на исходящем интерфейсе.
8.9. Запуск клиента без запуска сервера
Следующий сценарий, который мы рассмотрим, — это запуск клиента без запуска сервера. Если мы сделаем так и введем одну строку на стороне клиента, ничего не будет происходить. Клиент навсегда блокируется в своем вызове функции
recvfrom
