UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
16-25
shutdown
return
В конце раздела 16.2 мы привели результаты измерений времени выполнения для пяти различных реализаций функции
str_cli
fork
26.4. Использование потоков в эхо-сервере TCP
Теперь мы перепишем эхо-сервер TCP, приведенный в листинге 5.1, используя для каждого клиента по одному потоку вместо одного процесса. Кроме того, с помощью нашей функции
tcp_listen
Листинг 26.2. Эхо-сервер TCP, использующий потоки
//threads/tcpserv01.с
1 #include "unpthread.h"
2 static void *doit(void*); /* каждый поток выполняет эту функцию */
3 int
4 main(int argc, char **argv)
5 {
6 int listenfd, connfd;
7 pthread_t tid;
8 socklen_t addrlen, len;
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: tcpserv01 [ <host> ] <service or port>");
16 cliaddr = Malloc(addrlen);
17 for (;;) {
18 len = addrlen;
19 connfd = Accept(listenfd, cliaddr, &len);
20 Pthread_create(&tid, NULL, &doit, (void*)connfd);
21 }
22 }
23 static void*
24 doit(void *arg)
25 {
26 Pthread_detach(pthread_self());
27 str_echo((int)arg); /* та же функция, что и раньше */
28 Close((int)arg); /* мы закончили с присоединенным сокетом */
29 return (NULL);
30 }
17-21
accept
pthread_create
fork
doit
connfd
Мы преобразуем целочисленный дескриптор сокета к универсальному указателю (void). В ANSI С не гарантируется, что такое преобразование будет выполнено корректно, — мы можем быть уверены лишь в том, что оно сработает в тех системах, в которых размер целого числа не превышает размера указателя. К счастью, большинство реализаций Unix обладают этим свойством (см. табл. 1.5). Далее мы поговорим об этом подробнее.
23-30
doit
pthread_detach
str_echo
close
fork
Обратите также внимание на то, что главный поток не закрывает присоединенный сокет, что всегда происходило, когда параллельный сервер вызывал функцию
fork
close
fork
В этой программе имеется одна неявная ошибка, о которой рассказывается в разделе 26.5. Можете ли вы ее обнаружить? (См. упражнение 26.5.)
Передача аргументов новым потокам
Мы уже упомянули, что в листинге 26.2 мы преобразуем целочисленную переменную
connfd
void
В первую очередь, заметим, что мы не можем просто передать адрес
connfd
int main(int argc, char **argv) {
int listenfd, connfd;
...
for (;;) {
len = addrlen;