26.4. Использование потоков в эхо-сервере TCP
26.4. Использование потоков в эхо-сервере TCP
Теперь мы перепишем эхо-сервер TCP, приведенный в листинге 5.1, используя для каждого клиента по одному потоку вместо одного процесса. Кроме того, с помощью нашей функции tcp_listen мы сделаем эту версию не зависящей от протокола. В листинге 26.2 показан код сервера.
Листинг 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 не изменилась и осталась такой же, как в листинге 5.2. Когда эта функция завершается, следует вызвать функцию close для того, чтобы закрыть присоединенный сокет, поскольку этот поток использует все дескрипторы совместно с главным потоком. При использовании функции fork дочерний процесс не должен специально закрывать присоединенный сокет, так как при завершении дочернего процесса все открытые дескрипторы закрываются (см. упражнение 26.2).
Обратите также внимание на то, что главный поток не закрывает присоединенный сокет, что всегда происходило, когда параллельный сервер вызывал функцию fork. Это объясняется тем, что все потоки внутри процесса совместно используют все дескрипторы, поэтому если главному потоку потребуется вызвать функцию close, это приведет к закрытию соединения. Создание нового потока не влияет на счетчики ссылок для открытых дескрипторов, в отличие от того, что происходит при вызове функции fork.
В этой программе имеется одна неявная ошибка, о которой рассказывается в разделе 26.5. Можете ли вы ее обнаружить? (См. упражнение 26.5.)
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Стеки потоков и допустимые количества потоков
Стеки потоков и допустимые количества потоков Следует сделать еще два предостережения. Во-первых, подумайте о размере стека, который по умолчанию составляет 1 Мбайт. В большинстве случаев этого будет вполне достаточно, но если существуют какие-либо сомнения на сей счет,
Архивировать и кэшировать на сервере
Архивировать и кэшировать на сервере Как показали проведенные исследования, gzip-сжатие текстового файла «на лету» в 95–98% случаев позволяет сократить время на передачу файла браузеру. Если хранить архивированные копии файлов на сервере (в памяти proxy-сервера или просто на
Балансировка на сервере
Балансировка на сервере Другим популярным подходом для балансировки запросов является создание одного выделенного сервера, который отвечает за распределение запросов. Примерами таких серверов могут быть специальное оборудование или программные решения, например
Кэширование на сервере
Кэширование на сервере Такое программное обеспечение, как eAccelerator/xCache/ZendOptimizer для PHP, mod_perl для perl, mod_python для python и др., могут кэшировать серверные скрипты в скомпилированном состоянии, существенно ускоряя загрузку нашего сайта. Кроме этого, стоит найти профилирующий
26.3. Использование потоков в функции str_cli
26.3. Использование потоков в функции str_cli В качестве первого примера использования потоков мы перепишем нашу функцию str_cli. В листинге 16.6 была представлена версия этой функции, в которой использовалась функция fork. Напомним, что были также представлены и некоторые другие
7.5.4. Обработка на сервере
7.5.4. Обработка на сервере HTML-файлы могут обрабатываться прямо на сервере (так же, как выполняются файлы PHP). С одной стороны, это удобно, потому что код PHP можно будет вставлять в файлы с расширением htm, с другой стороны, HTML-файлы далеко небезопасны, и если хакер сможет их
Глава 13 Удаленная регистрация на сервере
Глава 13 Удаленная регистрация на сервере Многие серверы предоставляют доступ лишь к отдельным ресурсам компьютера, на котором они выполняются. Например, временной сервер, рассмотренный в главе 10, сообщает о показаниях системных часов, а сервер шрифтов, который будет
12.14.4 Запись о сервере имен
12.14.4 Запись о сервере имен Запись о сервере имен (Name Server — NS) идентифицирует сервер для домена. Если имеются подзоны, необходимы и элементы для дочерних серверов имен подзон, чтобы сервер с более высоким уровнем мог использовать указатели на серверы низшего уровня. Записи
12.2.1. Samba на сервере
12.2.1. Samba на сервере Из п.6.3 вы узнали, как использовать пакет Samba (www.samba.org) для просмотра общих ресурсов сети Windows. В этом параграфе я объясню, как настроить сервер Samba, чтобы открыть общий доступ к ресурсам компьютера под управлением Linux.С помощью Samba вы сможете;? предоставлять
13.4.1. Настройка кэширования на DNS-сервере
13.4.1. Настройка кэширования на DNS-сервере Для того, чтобы насладиться такой возможностью, следует в блок options файла named.conf добавить следующие параметры:forward first;forwarders { 81.3.165.35; 81.3.150.2;};Директива forwarders задает заключенный в фигурные скобки список IP-адресов DNS-серверов, которым
Развертывание на сервере
Развертывание на сервере Для выполнения упражнений, предлагаемых в этой книге, необходимо иметь доступ к серверной части служб SharePoint 3.0, которая может быть установлена на одном или нескольких серверах. Сервер должен соответствовать следующим требованиям.1 Операционная
Как зарегистрироваться на сервере
Как зарегистрироваться на сервере Что ж, ознакомившись с флагами, вы уже немножко разобрались, как функционирует программа TeamSpeak. Однако мы остановились на том, что зашли на сервер в первый раз с мизерными правами анонимного пользователя и теперь пытаемся здесь немножко
Память на сервере (все платформы)
Память на сервере (все платформы) Оценка памяти сервера включает множество факторов.* Работа сервера Firebird. Сервер Firebird осуществляет эффективное использование ресурсов сервера. Суперсервер (Superserver) после старта использует приблизительно 2 Мбайта памяти. Классический
Практическое использование потоков
Практическое использование потоков Когда измененяются папкиПеревод А. И. ЛегаловаАнглоязычный оригинал находится на сервере компании Reliable SoftwareВы когда-либо задались вопросом: каким оразом Проводник (Explorer) узнает о том, что некоторое действие должно модифицировать его