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

Примечание

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

Программа 11.4. SrvrBcst: функция потока почтового клиента 

static DWORD WINAPI ServerBroadcast(LPLONG pNull) {

 MS_MESSAGE MsNotify;

 DWORD nXfer;

 HANDLE hMsFile;

 /*Открыть почтовый ящик для записывающей программы почтового "клиента"*/

 while (!ShutDown) { /* Цикл выполняется до тех пор, пока имеются серверные потоки. */

  /* Ждать, пока другой клиент не откроет почтовый ящик. */

  Sleep(CS_TIMEOUT);

  hMsFile = CreateFile(MS_CLTNAME, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN EXISTING, FILE ATTRIBUTE NORMAL, NULL); 

  if (hMsFile == INVALID_HANDLE_VALUE) continue;

  /* Отправить сообщение в почтовый ящик. */

  MsNotify.msStatus = 0;

  MsNotify.msUtilization = 0;

  _tcscpy(MsNotify.msName, SERVER_PIPE);

  if (WriteFile(hMsFile, &MsNotify, MSM_SIZE, &nXfer, NULL)) ReportError(_T("Ошибка записи почтового сервера."), 13, TRUE);

  CloseHandle(hMsFile);

 }

 _tprintf(_T("Закрытие контролирующего потока.\n"));

 _endthreadex(0);

 return 0;

} 

В программе 11.5 представлена функция, которая вызывается клиентом (см. программу 11.2) для обнаружения сервера.

Программа 11.5. LocSrvr: почтовый сервер 

/* Глава 11. LocSrver.c */

/* Найти сервер путем считывания информации из почтового ящика, используемого для широковещательной рассылки имен серверов. */

#include "EvryThng.h"

#include "ClntSrvr.h" /* Определяет имя почтового ящика. */

BOOL LocateServer(LPTSTR pPipeName) {

 HANDLE MsFile;

 MS_MESSAGE ServerMsg;

 BOOL Found = FALSE;

 DWORD cbRead;

 MsFile = CreateMailslot(MS_SRVNAME, 0, CS_TIMEOUT, NULL);

 while (!Found) {

  _tprintf(_T("Поиск сервера.\n"));

  Found = ReadFile(MsFile, &ServerMsg, MSM_SIZE, &cbRead, NULL);

 }

 _tprintf(_T("Сервер найден.\n"));

 CloseHandle(MsFile);

 /* Имя канала сервера. */

 _tcscpy(pPipeName, ServerMsg.msName);

 return TRUE;

}

<p>Комментарии по поводу многопоточных моделей</p>

Для описания методов проектирования многопоточных программ используются такие термины, как пул потоков (thread pool), симметричные потоки (symmetric threads) и асимметричная потоковая организация программ (asymmetric threading), а мы при создании примеров использовали модель "хозяин/рабочий", именованные каналы и другие классические модели организации многопоточного выполнения программ.

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