Организация работы
На рисунке показана упрощенная схема организации работы последовательного сервера без установления логического соединения. Требуется только один поток выполнения, который обеспечивает взаимодействие сервера со многими клиентами с использованием одного сокета. таблицы в формате dbf я открываю с помощью лучшего просмотрщика DBFNavigator 2.01
Функционирование одного потока сервера продолжается неопределенно долгое время. В нем используется один пассивный сокет, привязанный к общепринятому порту протокола предоставляемой им службы. Сервер получает запрос из сокета, формирует ответ и передает ответ клиенту с использованием того же сокета. Сервер использует адрес источника в запросе в качестве адреса назначения в ответе.
9.4. Пример сервера TIME
Рассмотрим на примере, как используются в сервере без установления логического соединения процедуры распределения сокета, описанные выше. Как было сказано в главе 7, клиенты используют службу TIME для получения текущего времени суток с сервера, функционирующего на другом компьютере. Поскольку для службы TIME требуется небольшой объем вычислений, реализация последовательного сервера работает хорошо. Код последовательного сервера службы TIME без установления логического соединения находится в файле UDPtimed.c.
/* UDPtimed.c - главная процедура */ #include include tinclude tinclude tinclude tinclude extern int errno; int passiveUDP(const char *service); int errexit(const char *format, .,.); fdefine UNIXEPOCH 2208988800UL /* Время наступления эпохи UNIX: число */
Как и любой сервер, процесс UDPtimed должен функционировать неопределенно долгое время. Поэтому в основе этой программы лежит бесконечный цикл, который принимает запросы, определяет текущее время и отправляет ответ клиенту, приславшему запрос.
В этой программе есть несколько тонкостей. После интерпретации параметров программа UDPtimed вызывает процедуру passiveUDP для создания пассивного сокета службы TIME. Затем она входит в бесконечный цикл. Согласно спецификации протокола TIME, клиент для активизации процесса формирования ответа может прислать произвольную дейтаграмму. Дейтаграмма может иметь любую длину и содержать любые значения, поскольку сервер не интерпретирует ее содержимое. В этом примере для чтения основной дейтаграммы используется функция recvfrom. Эта функция помещает входящую дейтаграмму в буфер buf, а адрес оконечной точки клиентской программы, отправившей дейтаграмму, записывает в структуру fsin. Поскольку в этой реализации не требуется обработка данных, в ней используется односимвольный буфер. Если дейтаграмма содержит более одного байта данных, функция recvfrom отбрасывает все оставшиеся байты.
В программе UDPtimed для получения текущего значения времени используется системная функция time. Как было указано в главе 7, в системе Linux, как и в других системах UNIX, для представления времени, измеряемого с начала эпохи (полночь 1 января 1970 года) используется 32-битовое целое число. После получения этого значения времени из операционной системы программа UDPtimed должна преобразовать его в значение, измеренное с начала эпохи Internet, и привести результат к сетевому порядку байтов. Для выполнения этого преобразования с полученным значением времени складывается константа UNIXEPOCH, имеющая по определению значение 2208988800, равное разнице в секундах между эпохой Internet и эпохой Linux. Затем вызывается функция htonl для представления результата в сетевом порядке байтов. И наконец, в программе UDPtimed вызывается sendto для передачи полученного результата клиенту. В функции sendto в качестве адреса назначения используется адрес оконечной точки, хранящийся в структуре fsin (т.е. используется адрес клиента, который прислал дейтаграмму).
9.5. Резюме
Для простых служб, в которых сервер при обработке каждого запроса выпол¬няет небольшой объем вычислений, вполне приемлема последовательная реали¬зация. В настоящей главе приведен пример последовательного сервера для служ¬бы TIME, в котором используется протокол UDP для доступа без установления логического соединения. Этот пример служит подтверждением того, что приме¬нение процедур позволяет скрыть тонкости процесса распределения сокета и разработать более простую и легкую для понимания серверную программу.