UNIX: разработка сетевых приложений, стр. 254
43-47mydg_echoЗаключительная часть функции
mainbindЛистинг 22.15. Заключительная часть сервера UDP, связывающегося со всеми адресами
//advio/udpserv03.c50 /* связываем универсальный адрес */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 %s\n", 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-62SO_REUSEADDRmydg_echo63mainФункция
mydg_echoЛистинг 22.16. Функция mydg_echo
//advio/udpserv03.c65 void66 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 %s\n", Sock_ntop(myaddr, clilen));77 Sendto(sockfd, mesg, n, 0, pcliaddr, len);78 }79 }65-6671-78recvfromsendtoЗапустим эту программу на нашем узле
solarishme0solaris % <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>При помощи утилиты
netstatsolaris % <b>netstat -na | grep 9877</b>127.0.0.1.9877 Idle10.0.0.200.9877 Idle *.9877 Idle192.129.100.100.9877 Idle *.9877 Idle *.9877 IdleСледует отметить, что для простоты мы создаем по одному дочернему процессу на сокет, хотя возможны другие варианты. Например, чтобы ограничить число процессов, программа может управлять всеми дескрипторами сама, используя функцию
selectforkselect22.7. Параллельные серверы UDP
Большинство серверов UDP являются последовательными (iterative): сервер ждет запрос клиента, считывает запрос, обрабатывает его, отправляет обратно ответ и затем ждет следующий клиентский запрос. Но когда обработка запроса клиента занимает длительное время, желательно так или иначе совместить во времени обработку различных запросов.