UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
В листинге 30.2 показана функция
main
Листинг 30.2. Функция main для параллельного сервера TCP
//server/serv01.c
1 include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int listenfd, connfd;
6 pid_t childpid;
7 void sig_chld(int), sig_int(int), web_child(int);
8 socklen_t clilen, addrlen;
9 struct sockaddr *cliaddr;
10 if (argc == 2)
11 listenfd = Tcp_listen(NULL, argv[1], &addrlen);
12 else if (argc == 3)
13 listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
14 else
15 err_quit("usage: serv01 [ <host> ] <port#>");
16 cliaddr = Malloc(addrlen);
17 Signal(SIGCHLD, sig_chld);
18 Signal(SIGINT, sig_int);
19 for (;;) {
20 clilen = addrlen;
21 if ((connfd = accept(listenfd, cliaddr, &clilen)) < 0) {
22 if (errno == EINTR)
23 continue; /* назад к for() */
24 else
25 err_sys("accept error");
26 }
27 if ((childpid = Fork()) == 0) { /* дочерний процесс */
28 Close(listenfd); /* закрываем прослушиваемый сокет */
29 web_child(connfd); /* обрабатываем запрос */
30 exit(0);
31 }
32 Close(connfd); /* родительский процесс закрывает
присоединенный сокет */
33 }
34 }
Эта функция аналогична функции, показанной в листинге 5.9: она вызывает функцию
fork
SIGCHLD
tcp_listen
sig_chld
printf
Мы также перехватываем сигнал
SIGINT
Листинг 30.3. Обработчик сигнала SIGINT
//server/serv01.c
35 void
36 sig_int(int signo)
37 {
38 void pr_cpu_time(void);
39 pr_cpu_time();
40 exit(0);
41 }
В листинге 30.4 показана функция
pr_cpu_time
Листинг 30.4. Функция pr_cpu_time: вывод полного времени центрального процессора
//server/pr_cpu_time.c
1 #include "unp.h"
2 #include <sys/resource.h>
3 #ifndef HAVE_GETRUSAGE_PROTO
4 int getrusage(int, struct rusage*);
5 #endif
6 void
7 pr_cpu_time(void)
8 {
9 double user, sys;
10 struct rusage myusage, childusage;
11 if (getrusage(RUSAGE_SELF, &myusage) < 0)
12 err_sys("getrusage error");
13 if (getrusage(RUSAGE_CHILDREN, &childusage) < 0)
14 err_sys("getrusage error");
15 user = (double)myusage.ru_utime.tv_sec +
16 myusage.ru_utime.tv_usec / 1000000.0;
17 user += (double)childusage.ru_utime.tv_sec +
18 childusage.ru_utime.tv_usec / 1000000.0;
19 sys = (double)myusage.ru_stime.tv_sec +
20 myusage.ru_stime.tv_usec / 1000000.0;
21 sys += (double)childusage.ru_stime.tv_sec +
22 childusage.ru_stime.tv_usec / 1000000.0;
21 printf("nuser time = %g, sys time = %gn", user, sys);
22 }
Функция
getrusage
RUSAGE_SELF
RUSAGE_CHILDREN
Возвращаясь к листингу 30.2, мы видим, что для обработки каждого клиентского запроса вызывается функция
web_child