Искусство программирования для Unix
Шрифт:
Для того чтобы изящно, в духе Unix использовать сокеты, следует начинать с разработки используемого между ними протокола прикладного уровня, т.е. набора запросов и ответов, лаконично выражающего семантику данных, которыми будут обмениваться программы. Некоторые основные вопросы в проектировании протоколов прикладного уровня уже рассматривались в главе 5.
Сокеты поддерживаются во всех последних операционных системах семейства Unix, Microsoft Windows, а также в классической MacOS.
7.2.6.5.1. Учебный пример: PostgreSQL
PostgreSQL — программа с открытым исходным кодом
Вместо этого пакет PostgreSQL включает в себя сервер, который называется postmaster, и по крайней мере 3 клиентских приложения. В машине в фоновом режиме запускается один серверный процесс postmaster. Данный процесс имеет исключительный доступ к файлам базы данных. Он принимает запросы на мини-языке SQL-запросов посредством TCP/IP-сокетов, а также возвращает ответы в текстовом формате. Запущенный пользователем PostgreSQL-клиент открывает сеанс связи с сервером postmaster и выполняет с ним SQL-транзакции. Одновременно сервер способен обрабатывать несколько клиентских сеансов, а их запросы последовательно располагаются так, что не пересекаются друг с другом.
Поскольку клиентская и серверная части обособлены, серверу не требуется выполнять других задач, кроме интерпретации SQL-запросов от клиента и отправки SQL-отчетов в обратном направлении. С другой стороны, клиентам не требуется иметь какую-либо информацию о том, как хранится база данных. Клиенты могут быть специализированы для решения различных задач и иметь разные пользовательские интерфейсы.
Подобная организация весьма типична для баз данных в операционной системе Unix — настолько типична, что часто возможно сочетать и подбирать SQL-клиенты и SQL-серверы. Проблемы взаимодействия связаны с номером ТСРДР-порта SQL-сервера, а также с тем, поддерживают ли клиент и сервер один и тот же диалект SQL.
7.2.6.5.2. Учебный пример: Freeciv
В главе 6 игра Freeciv была представлена в качестве иллюстрации прозрачного формата данных. Однако более важным для поддержки игры с множеством участников является разделение кода на клиентскую и серверную части. Freeciv является характерным примером программы, в которой приложение должно быть распределено в сети и поддерживает связь через ТСР/1Р-сокеты.
Состояние запущенной игры Freeciv обслуживается серверным процессом, ядром игры. Игроки запускают GUI-клиенты, которые обмениваются информацией и командами с сервером посредством пакетного протокола. Вся игровая логика обрабатывается на сервере. Детали GUI-интерфейса обрабатываются клиентом. Различные клиенты поддерживают разные стили интерфейсов.
Организация данной игры весьма типична для сетевых игр с множеством участников. Пакетный протокол использует в качестве транспорта протокол TCP/IP, поэтому один сервер способен поддерживать клиентов, запущенных на различных узлах в Internet. В других играх, более похожих на симуляторы реального времени (особенно боевые игры от первого лица), используется протокол дейтаграмм Internet (UDP), и низкая задержка достигается за счет некоторой ненадежности доставки какого-либо определенного пакета. В таких играх пользователи, как правило, непрерывно выполняют управляющие действия, поэтому единичные
7.2.6.6. Общая память
Тогда как два процесса, использующие для информационного обмена сокеты, могут выполняться на различных машинах (и в действительности могут быть разделены Internet-соединением, "огибающим" половину планеты), общая память (shared memory) требует, чтобы поставщики и потребители данных одновременно находились в памяти одного компьютера. Однако, если процессы, обменивающиеся данными, могут получить доступ к одной физической памяти, то общая память будет самым быстрым способом передачи информации между ними.
Общая память может быть представлена различными API-интерфейсами, но в современных Unix-системах реализация обычно зависит от использования функции ттар(2) для отображения файлов в общую память. В стандарте POSIX определяется средство shm_open(3) с API-интерфейсом, поддерживающим использование файлов в качестве общей памяти. Данная функция, главным образом, предоставляет операционной системе возможность не сбрасывать на диск данные псевдофайла.
Так как доступ к общей памяти автоматически не сериализуется в каком-либо порядке, подобном вызовам чтения и записи, программы с общей памятью должны обрабатывать проблемы конфликтов и взаимоблокировок самостоятельно, обычно путем использования семафоров, находящихся в совместно используемом сегменте. В данном случае возникают проблемы, подобные проблемам мультипроцессной обработки (их обсуждение приведено в конце данной главы), но они являются более управляемыми, так как по^умолчанию программы не используют общую память. Поэтому проблемы становятся более контролируемыми.
В системах, где это доступно и надежно работает, средство учета (scoreboard facility) Web-сервера Apache применяет общую память для обмена данными между главным процессом Apache и пулом распределения нагрузки образов Apache, которыми он управляет. В современных реализациях системы X также применяется общая память для передачи больших образов между клиентом и сервером, когда они находятся в памяти одной машины. В данном случае эта методика применяется для того, чтобы избежать издержек связи с использованием сокетов. Оба варианта применения представляют собой средство повышения производительности, обоснованное скорее опытом и тестами, чем архитектурным выбором.
Вызов ттар(2) поддерживается во всех современных Unix-системах, включая Linux и версии BSD с открытым исходным кодом. Он описан в единой спецификации Unix (Single Unix Specification). Обычно он недоступен в Windows, классической MacOS и других операционных системах.
До того как появилась специализированная функция ттар(2), общим способом сообщения двух процессов было открытие одного и того же файла и последующее удаление данного файла. Файл не удалялся до тех пор, пока не были закрыты все открытые дескрипторы данного файла, но некоторые старые Unix-системы использовали обнуление счетчика ссылок как указание на то, что обновление дисковой копии файла можно прекратить. Недостатком в этом случае было то, что вспомогательным запоминающим устройством была файловая система, а не устройство подкачки. Отключить файловую систему, на которой находился удаляемый файл, было невозможно до тех пор, пока не были закрыты использующие его программы, а подключение новых процессов к существующему сегменту общей памяти, выполненное таким способом, было в лучшем случае сложным.