Пример однопотокового сервера службы ECHO

Опубликовано в Технологии > Серверные технологии

Для пояснения описанных выше принципов и иллюстрации того, как один поток может применяться для обеспечения параллельной работы, воспользуемся следующим примером. Рассмотрим файл TCPmechod.c, который содержит код сервера, реализующего службу ECHO.

/* Файл TCPmechod.c - главная процедура echo */
tinclude  tinclude  tinclude  tinclude 
tinclude  tinclude  tinclude 
tdefine    QLEN	32	/* Максимальная длина очереди соединений */
tdefine    BUFSIZE 4096
extern int errno;
int        errexit(const char *format, ...);
int        passiveTCP(const char *service, int qlen);
int        echo(int fd);

Выполнение потока этого сервера, как и выполнение ведущего потока сервера в параллельной реализации, начинается с открытия пассивного сокета в общепринятый порт. В этом примере используется системная функция getdtablesize для определения максимального числа дескрипторов, а затем применяются макрокоманды FD_ZER0 и FDJ3ET для создания битового вектора, соответствующего дескрипторам сокетов, которые должны контролироваться функцией select. Затем сервер входит в бесконечный цикл, в котором он вызывает функцию select для ожидания готовности к работе одного или нескольких дескрипторов.

Если готов дескриптор ведущего сокета, сервер вызывает функцию accept для получения нового соединения. Он добавляет дескриптор нового соединения к управляемому им набору и снова переходит в состояние ожидания активизации следующих дескрипторов. Если же готов дескриптор ведомого сокета, сервер вызывает процедуру echo, в которой вызывается функция read для получения данных из соединения и функция write для отправки их назад клиенту. Если один из дескрипторов ведомого сокета сообщает о получении признака конца файла, сервер закрывает дескриптор и использует макрокоманду FD_CLR для удаления его из набора дескрипторов, используемых функцией select.

13.6. Резюме

Выполнение обработки данных в параллельных серверах часто активизируется в результате поступления самих данных, а не с помощью механизма квантования времени базовой операционной системы. В тех случаях, если предоставляемая служба требует небольшого объема обработки, для такого же эффективного обслуживания соединений с многочисленными клиентами, как и в варианте на основе нескольких потоков или процессов, может использоваться один поток выполнения, в котором осуществляется асинхронный ввод/вывод.

В однопотоковой реализации один поток выполнения берет на себя обязанности одного ведущего и нескольких ведомых потоков. Если готов к работе ведущий сокет, единственный поток сервера вызывает функцию accept для получения нового соединения. А если готов любой другой сокет, поток сервера принимает запрос и передает ответ. В приведенном примере с сервером службы ECHO показано, как обеспечить параллельную обработку в одном потоке, а также проиллюстрированы тонкости программирования. Клиническая диета. Купить смеси для зондового питания. Лечебное питание.

Поскольку функция select перед возвратом управления очищает все дескрипторы, не доступные для чтения или записи, в этом коде набор активных дескрипторов копируется в переменную rfds при каждом проходе по циклу while.

Материал для дальнейшего изучения

Качественная спецификация протокола отличается тем, что она не ограничивает возможности реализации. Например, в однопотоковом сервере, описанном в настоящей главе, осуществлен протокол службы ECHO, который определен в документе [120], а в главах 11 и 12 приведены примеры альтернативных реализаций, созданных на основе той же спецификации протокола. В этих реализациях, соответственно, используются несколько процессов (каждый из которых содержит один поток выполнения) или один многопотоковый процесс.

Упражнения

  1. Проведите эксперимент, который доказывает, что сервер службы ECHO, приведенный в данном примере, обеспечивает параллельное обслуживание соединений.
  2. Имеет ли смысл использовать реализацию, описанную в данной главе, для создания службы DAYTIME? Объясните ваш ответ.
  3. Прочитайте оперативную документацию, чтобы узнать, как именно представлены дескрипторы в списке, передаваемом функцией select. Напишите макрокоманды FDJ3ET и FD_CLR.
  4. Сравните производительность сервера, в котором используется один поток, и сервера, в котором используется несколько процессов на компьютере с несколькими процессорами. При каких обстоятельствах версия с одним потоком будет работать лучше (или одинаково) по сравнению с версией, в которой используется несколько процессов?
  5. Предположим, что к серверу, который рассматривается в качестве примера в данной главе, одновременно обращается много клиентов (скажем, 100). Объясните, что может наблюдать каждый из этих клиентов.
  6. Может ли сервер, в котором используется один поток выполнения, когда-либо лишить одного клиента доступа к службе, снова и снова обслуживая запросы другого? Может ли сервер, в котором используется несколько потоков, или сервер, в котором используется несколько однопотоковых процессов, когда-либо отказать в обслуживании какому-либо клиенту? Объясните ваш ответ.