UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Функция
child_main
Листинг 30.19. Функция child_main: передача дескриптора в сервере с предварительным порождением дочерних процессов
//server/child05.c
23 void
24 child_main(int i, int listenfd, int addrlen)
25 {
26 char c;
27 int connfd;
28 ssize_t n;
29 void web_child(int);
30 printf("child %ld startingn", (long)getpid());
31 for (;;) {
32 if ((n = Read_fd(STDERR_FILENO, &c, 1, &connfd)) == 0)
33 err_quit("read_fd returned 0");
34 if (connfd < 0)
35 err_quit("no descriptor from read_fd");
36 web_child(connfd); /* обработка запроса */
37 Close(connfd);
38 Write(STDERR_FILENO, "", 1); /* сообщаем родительскому процессу
о том, что дочерний освободился */
39 }
40 }
32-33
accept
read_fd
38
write
В табл. 30.1 при сравнении строк 4 и 5 мы видим, что данный сервер медленнее, чем версия, рассмотренная нами в предыдущем разделе, которая использовала блокировку потоками взаимного исключения. Передача дескриптора по каналу от родительского процесса к дочернему и запись одного байта в канал для сообщения родительскому процессу о завершении обработки клиентского запроса занимает больше времени, чем блокирование и разблокирование взаимного исключения или файла.
В табл. 30.2 показаны значения счетчиков
child_count
Child
SIGINT
30.10. Параллельный сервер TCP: один поток для каждого клиента
Предыдущие пять разделов были посвящены рассмотрению серверов, в которых для обработки клиентских запросов используются дочерние процессы, либо заранее порождаемые с помощью функции
fork
Наша первая версия сервера с использованием потоков показана в листинге 30.20. Это модификация листинга 30.2: в ней создается один поток для каждого клиента вместо одного дочернего процесса для каждого клиента. Эта версия во многом похожа на сервер, представленный в листинге 26.2.
Листинг 30.20. Функция main для сервера TCP, использующего потоки
//server/serv06.c
1 #include "unpthread.h"
2 int
3 main(int argc, char **argv)
4 {
5 int listenfd, connfd;
6 void sig_int(int);
7 void *doit(void*);
8 pthread_t tid;
9 socklen_t clilen, addrlen;
10 struct sockaddr *cliaddr;
11 if (argc == 2)
12 listenfd = Tcp_listen(NULL, argv[1], &addrlen);
13 else if (argc == 3)
14 listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
15 else
16 err_quit("usage: serv06 [ <host> ] <port#>");
17 cliaddr = Malloc(addrlen);
18 Signal (SIGINT, sig_int);
19 for (;;) {
20 clilen = addrlen;
21 connfd = Accept(listenfd, cliaddr, &clilen);
22 Pthread_create(&tid, NULL, &doit, (void*)connfd);
23 }
24 }
25 void*
26 doit(void *arg)
27 {
28 void web_child(int);
29 Pthread_detach(pthread_self());
30 web_child((int)arg);
31 Close((int)arg);
32 return (NULL);
33 }
19-23
pthread_create
doit
25-33
doit
Doit
web_child