UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
43-47
mydg_echo
Заключительная часть функции
main
bind
Листинг 22.15. Заключительная часть сервера UDP, связывающегося со всеми адресами
//advio/udpserv03.c
50 /* связываем универсальный адрес */
51 sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
52 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
53 bzero(&wildaddr, sizeof(wildaddr));
54 wildaddr.sin_family = AF_INET;
55 wildaddr.sin_addr.s_addr = htonl(INADDR_ANY);
56 wildaddr.sin_port = htons(SERV_PORT);
57 Bind(sockfd, (SA*)&wildaddr, sizeof(wildaddr));
58 printf("bound %sn", Sock_ntop((SA*)&wildaddr, sizeof(wildaddr)));
59 if ((pid = Fork()) == 0) { /* дочерний процесс */
60 mydg_echo(sockfd, (SA*)&cliaddr, sizeof(cliaddr), (SA*)sa);
61 exit(0); /* не выполняется */
62 }
63 exit(0);
64 }
50-62
SO_REUSEADDR
mydg_echo
63
main
Функция
mydg_echo
Листинг 22.16. Функция mydg_echo
//advio/udpserv03.c
65 void
66 mydg_echo(int sockfd, SA *pcliaddr, socklen_t clilen, SA *myaddr)
67 {
68 int n;
69 char mesg[MAXLINE];
70 socklen_t len;
71 for (;;) {
72 len = clilen;
73 n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);
74 printf("child %d, datagram from %s", getpid(),
75 Sock_ntop(pcliaddr, len));
76 printf(", to %sn", Sock_ntop(myaddr, clilen));
77 Sendto(sockfd, mesg, n, 0, pcliaddr, len);
78 }
79 }
65-66
71-78
recvfrom
sendto
Запустим эту программу на нашем узле
solaris
hme0
solaris % <b>udpserv03</b>
bound 127.0.0.1:9877 <i>интерфейс закольцовки</i>
bound 10.0.0.200:9877 <i>направленный адрес интерфейса hme0:1</i>
bound 10.0.0.255:9877 <i>широковещательный адрес интерфейса hme0:1</i>
bound 192.168.1.20:9877 <i>направленный адрес интерфейса hme0</i>
bound 192.168.1.255:9877 <i>широковещательный адрес интерфейса hme0</i>
bound 0.0.0.0.9877 <i>универсальный адрес</i>
При помощи утилиты
netstat
solaris % <b>netstat -na | grep 9877</b>
127.0.0.1.9877 Idle
10.0.0.200.9877 Idle
*.9877 Idle
192.129.100.100.9877 Idle
*.9877 Idle
*.9877 Idle
Следует отметить, что для простоты мы создаем по одному дочернему процессу на сокет, хотя возможны другие варианты. Например, чтобы ограничить число процессов, программа может управлять всеми дескрипторами сама, используя функцию
select
fork
select
22.7. Параллельные серверы UDP
Большинство серверов UDP являются последовательными (iterative): сервер ждет запрос клиента, считывает запрос, обрабатывает его, отправляет обратно ответ и затем ждет следующий клиентский запрос. Но когда обработка запроса клиента занимает длительное время, желательно так или иначе совместить во времени обработку различных запросов.