Читаем Системное программирование в среде Windows полностью

• Записывающей программе (клиенту) не известно достоверно, все ли, только некоторые или какая-то одна из программ считывания (сервер) получили сообщение.

• Почтовые ящики могут находиться в любом месте сети.

• Размер сообщений ограничен.

Использование почтовых ящиков требует выполнения следующих операций:

• Каждый сервер создает дескриптор почтового ящика с помощью функции CreateMailSlot.

• После этого сервер ожидает получения почтового сообщения, используя функцию ReadFile.

• Клиент, обладающий только правами записи, должен открыть почтовый ящик, вызвав функцию CreateFile, и записать сообщения, используя функцию WriteFile. В случае отсутствия ожидающих программ считывания попытка открытия почтового ящика завершится ошибкой (наподобие "имя не найдено").

Сообщение клиента может быть прочитано всеми серверами; все серверы получают одно и то же сообщение.

Существует еще одна возможность. В вызове функции CreateFile клиент может указать имя почтового ящика в следующем виде:

\\*\mailslot\mailslotname

При этом символ звездочки (*) действует в качестве группового символа (wildcard), и клиент может обнаружить любой сервер в пределах имени домена — группы систем, объединенных общим именем, которое назначается администратором сети. 

<p>Использование почтовых ящиков</p>

Рассмотренный перед этим клиент-серверный процессор командной строки предполагает несколько возможных способов его использования. Рассмотрим один из сценариев, в котором решается задача обнаружения сервера в только что упомянутой клиент-серверной системе (программы 11.2 и 11.3).

Сервер приложения (application server), действуя в качестве почтового клиента (mailslot client), периодически осуществляет широковещательную рассылку своего имени и имени именованного канала. Любой клиент приложения (application client), которому требуется найти сервер, может получить это имя, действуя в качестве сервера почтовых ящиков (mailslot server). Аналогичным образом сервер командной строки может периодически осуществлять широковещательную рассылку своего состояния, включая информацию о коэффициенте использования, клиентам. Это соответствует ситуации, в которой имеется одна записывающая программа (почтовый клиент) и несколько считывающих программ (почтовых серверов). Если бы почтовых клиентов (то есть серверов приложения) было несколько, то ситуация описывалась бы отношением типа "многие ко многим".

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

Обмен ролями терминов клиент и сервер в данном контексте может несколько сбивать с толку, однако заметьте, что сервер именованного канала и почтовый сервер выполняют вызовы функций CreateNamedPipe (или CreateMailSlot), тогда как клиент (именованного канала или почтового ящика) создает соединение, используя функцию CreateFile. Кроме того, в обоих случаях первый вызов функции WriteFile выполняется клиентом, а первый вызов функции ReadFile выполняется сервером.

Использование почтовых ящиков в соответствии с первым из описанных возможных вариантов иллюстрируется на рис. 11.3.

<p>Создание и открытие почтового ящика</p>

Для создания почтового ящика и получения дескриптора, который можно будет использовать в операциях ReadFile, почтовые серверы (программы считывания) вызывают функцию CreateMailslot. На одном компьютере может находиться только один почтовый ящик с данным именем, но один и тот же почтовый ящик может использоваться несколькими системами в сети, что обеспечивает возможность работы с ним нескольких программ считывания. 

Рис. 11.3. Использование клиентами почтового ящика для обнаружения сервера

HANDLE CreateMailslot(LPCTSTR lpName, DWORD cbMaxMsg, DWORD dwReadTimeout, LPSECURITY_ATTRIBUTES lpsa) 

Параметры

lpName — указатель на строку с именем почтового ящика, которое должно иметь следующий вид:

\\.\mailslot\[путь]имя

Имя должно быть уникальным. Точка (.) указывает на то, что почтовый ящик создается на локальном компьютере.

cbMaxMsg — максимальный размер сообщения (в байтах), которые может записывать клиент. Значению 0 соответствует отсутствие ограничений.

dwReadTimeOut — длительность интервала ожидания (в миллисекундах) для операции чтения. Значению 0 соответствует немедленный возврат, а значению MAILSLOT_WAIT_FOREVER — неопределенный период ожидания (который может длиться сколь угодно долго). 

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже