UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Вспомните наше обсуждение в конце раздела 22.2. Если узел использует более распространенную модель системы с гибкой привязкой (см. раздел 8.8), IP-адрес получателя может отличаться от IP-адреса принимающего интерфейса. В этом случае мы можем определить только адрес получателя дейтаграммы, который не обязательно должен быть адресом, присвоенным принимающему интерфейсу. Чтобы определить принимающий интерфейс, требуется параметр сокета IP_RECVIF или IPV6_PKTINFO.
В листинге 22.13 показана первая часть примера применения этой технологии к эхо-серверу UDP, который связывается со всеми адресами направленной передачи, широковещательной передачи и, наконец, с универсальными адресами.
Листинг 22.13. Первая часть сервера UDP, который с помощью функции bind связывается со всеми адресами
//advio/udpserv03.c 1 #include "unpifi.h" 2 void mydg_echo(int, SA*, socklen_t, SA*); 3 int 4 main(int argc, char **argv) 5 { 6 int sockfd; 7 const int on = 1; 8 pid_t pid; 9 struct ifi_info *ifi, *ifihead;10 struct sockaddr_in *sa, cliaddr, wildaddr;11 for (ifihead = ifi = Get_ifi_info(AF_INET, 1);12 ifi != NULL; ifi = ifi->ifi_next) {13 /* связываем направленный адрес */14 sockfd = Socket(AF_INET, SOCK_DGRAM, 0);15 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));16 sa = (struct sockaddr_in*)ifi->ifi_addr;17 sa->sin_family = AF_INET;18 sa->sin_port = htons(SERV_PORT);19 Bind(sockfd, (SA*)sa, sizeof(*sa));20 printf("bound %sn", Sock_ntop((SA*)sa, sizeof(*sa)));21 if ((pid = Fork()) == 0) { /* дочерний процесс */22 mydg_echo(sockfd, (SA*)&cliaddr, sizeof(cliaddr), (SA*)sa);23 exit(0); /* не выполняется */24 }11-12get_ifi_infoifi_info13-20SO_REUSEADDRSERV_PORTНе все реализации требуют, чтобы был установлен этот параметр сокета. Например, Беркли-реализации не требуют этого параметра и позволяют с помощью функции bind связать уже связанный порт, если новый связываемый IP-адрес не является универсальным адресом и отличается от всех IP-адресов, уже связанных с портом. Однако Solaris 2.5 для успешного связывания с одним и тем же портом второго адреса направленной передачи требует установки этого параметра.
21-24forkmydg_echoВ листинге 22.14 показана следующая часть функции
mainЛистинг 22.14. Вторая часть сервера UDP, который с помощью функции bind связывается со всеми адресами
//advio/udpserv03.c25 if (ifi->ifi_flags & IFF_BROADCAST) {26 /* пытаемся связать широковещательный адрес */27 sockfd = Socket(AF_INET, SOCK_DGRAM, 0);28 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));29 sa = (struct sockaddr_in*)ifi->ifi_brdaddr;30 sa->sin_family = AF_INET;31 sa->sin_port = htons(SERV_PORT);32 if (bind(sockfd, (SA*)sa, sizeof(*sa)) < 0) {33 if (errno == EADDRINUSE) {34 printf("EADDRINUSE: %sn",35 Sock_ntop((SA*)sa, sizeof(*sa)));36 Close(sockfd);37 continue;38 } else39 err_sys("bind error for %s",40 Sock_ntop((SA*)sa, sizeof(*sa)));41 }42 printf("bound %sn", Sock_ntop((SA*)sa, sizeof(*sa)));43 if ((pid = Fork()) == 0) { /* дочерний процесс */44 mydg_echo(sockfd, (SA*)&cliaddr, sizeof(cliaddr),45 (SA*)sa);46 exit(0); /* не выполняется */47 }48 }49 }25-42bindEADDRINUSEbind
