UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Функция
child_mainЛистинг 30.19. Функция child_main: передача дескриптора в сервере с предварительным порождением дочерних процессов
//server/child05.c23 void24 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-33acceptread_fd38writeВ табл. 30.1 при сравнении строк 4 и 5 мы видим, что данный сервер медленнее, чем версия, рассмотренная нами в предыдущем разделе, которая использовала блокировку потоками взаимного исключения. Передача дескриптора по каналу от родительского процесса к дочернему и запись одного байта в канал для сообщения родительскому процессу о завершении обработки клиентского запроса занимает больше времени, чем блокирование и разблокирование взаимного исключения или файла.
В табл. 30.2 показаны значения счетчиков
child_countChildSIGINT30.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 else16 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-23pthread_createdoit25-33doitDoitweb_child
