В нашем примере все клиенты отправляют серверу свои запросы с помощью единой серверной очереди FIFO. Общеизвестное имя очереди (/tmp/seqnum_sv) определяется в заголовочном файле в листинге 44.6. Данное имя — постоянное, поэтому все клиенты знают, как соединиться с сервером. (В примере очередь FIFO создается в каталоге /tmp, поскольку это позволяет запускать программы без изменений в большинстве систем. Но, как отмечается в разделе 38.7, создание файлов в публичных каталогах, доступных для записи, таких как /tmp, чревато различными проблемами с безопасностью и в реальных приложениях является нежелательным.)
При работе с клиент-серверными приложениями мы будем постоянно сталкиваться с понятием «общеизвестный адрес» (или имя), с помощью которого сервер становится доступным для клиентов. Это один из механизмов, позволяющий клиентам определять местонахождение сервера. Еще один вариант заключается в предоставлении некоего DNS-сервера, в котором можно регистрировать различные сервисы, предоставляемые другими серверами. Когда клиенту нужно узнать местоположение сервиса, он связывается с DNS-сервером. Благодаря такому решению процедура размещения серверов становится более гибкой, хотя для этого необходимо проделать некую дополнительную работу. Естественно, в таком случае клиенты и серверы должны знать, где находится сам DNS-сервер; обычно он привязан к общеизвестному адресу.
Однако для отправки ответов всем клиентам недостаточно единственной очереди FIFO, поскольку клиенты стали бы за нее соперничать и, возможно, читать ответные сообщения друг друга вместо своих собственных. Таким образом, каждый клиент создает уникальную очередь FIFO, с помощью которой сервер доставляет ему свой ответ. При этом сервер должен знать, как найти данную очередь. Одним из решений проблемы является генерирование клиентом пути к своей очереди и передача этого пути вместе с запросом. Как вариант, клиент и сервер могут задействовать соглашение относительно построения пути к очереди FIFO; в таком случае вместе с запросом клиент будет отправлять информацию, необходимую для определения данного пути. Именно это решение используется в нашем примере. Имя каждой клиентской очереди формируется по шаблону (CLIENT_FIFO_TEMPLATE), который состоит из пути с идентификатором клиентского процесса. Применение идентификатора процесса упрощает генерирование имени, уникального для каждого конкретного клиента.
На рис. 44.6 показано, как наше приложение использует очереди FIFO для взаимодействия серверного и клиентского процессов.
Заголовочный файл (см. листинг 44.6) описывает форматы запросов, передающиеся от клиентов к серверу, и ответов, которые сервер возвращает клиентам.
Как вы помните, данные внутри каналов и очередей FIFO представляют собой потоки байтов; границ между отдельными сообщениями не существует. То есть при передаче нескольких сообщений одному процессу (в данном случае серверу) отправитель и получатель должны иметь одинаковое представление о том, как эти сообщения разделяются. Здесь возможны различные подходы.
• Каждое сообщение заканчивается
• Каждое сообщение содержит
•