UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Доставка множества экземпляров одного и того же сигнала вызывает проблему, к рассмотрению которой мы и приступим.
Рис. 5.3. Клиент завершает работу, закрывая все пять соединений и завершая все пять дочерних процессов
Сначала мы запускаем сервер в фоновом режиме, а затем — новый клиент. Наш сервер, показанный в листинге 5.1, несколько модифицирован — теперь в нем вызывается функция
signal
SIGCHLD
linux % <b>tcpserv03 &</b>
[1] 20419
linux % <b>tcpcli04 206.62.226.35</b>
<b>hello </b><i>мы набираем эту строку</i>
hello <i>и она отражается сервером</i>
<b>^D</b> <i>мы набираем символ конца файла</i>
child 20426 terminated <i>выводится сервером</i>
Первое, что мы можем заметить, — данные выводит только одна функция
printf
ps
PID TTY TIME CMD
20419 pts/6 00:00:00 tcpserv03
20421 pts/6 00:00:00 tcpserv03 <defunct>
20422 pts/6 00:00:00 tcpserv03 <defunct>
20423 pts/6 00:00:00 tcpserv03 <defunct>
Установки обработчика сигнала и вызова функции
wait
Правильным решением будет вызвать функцию
waitpid
wait
sigchld
SIGCHLD
waitpid
WNOHANG
waitpid
wait
wait
В листинге 5.9 показана окончательная версия нашего сервера. Он корректно обрабатывает возвращение ошибки
EINTR
accept
waitpid
Листинг 5.8. Окончательная (корректная) версия функции sig_chld, вызывающая функцию waitpid
//tcpcliserv/sigchldwaitpid.c
1 #include "unp.h"
2 void
3 sig_chld(int signo)
4 {
5 pid_t pid;
6 int stat;
7 while ((pid = waitpid(-1, &stat, WNOHANG)) >0)
8 printf("child %d terminatedn", pid);
9 return;
10 }
Листинг 5.9. Окончательная (корректная) версия TCP-сервера, обрабатывающего ошибку EINTR функции accept
//tcpcliserv/tcpserv04.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int listenfd, connfd;
6 pid_t childpid;
7 socklen_t clilen;
8 struct sockaddr_in cliaddr, servaddr;
9 void sig_chld(int);
10 listenfd = Socket(AF_INET, SOCK_STREAM, 0);
11 bzero(&servaddr, sizeof(servaddr));
12 servaddr.sin_family = AF_INET;
13 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
14 servaddr.sin_port = htons(SERV_PORT);
15 Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
16 Listen(listenfd, LISTENQ);
17 Signal(SIGCHLD, sig_chld); /* нужно вызвать waitpid() */
18 for (;;) {
19 clilen = sizeof(cliaddr);
20 if ((connfd = accept(listenfd, (SA*)&cliaddr, &clilen)) < 0) {
21 if (errno == EINTR)
22 continue; /* назад к for() */
23 else
24 err_sys("accept error");
25 }
26 if ((childpid = Fork()) == 0) { /* дочерний процесс */