Вход/Регистрация
Системное программирование в среде Windows
вернуться

Харт Джонсон М.

Шрифт:

/* Отправить признак конца ответа. */

Response.Status = 1;

strcpy(Response.Record, "");

WriteFile(hNamedPipe, &Response, RS_SIZE, &nXfer, NULL);

}

/* Конец основного командного цикла. Получить следующую команду. */

/* Принудительно завершить выполнение потока, если он все еще активен.*/

GetExitCodeThread(hConTh, &ConThStatus);

if (ConThStatus == STILL_ACTIVE) {

hClient = CreateFile(SERVER_PIPE, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN EXISTING, FILE ATTRIBUTE NORMAL, NULL); 

if (hClient != INVALID_HANDLE_VALUE) CloseHandle (hClient);

WaitForSingleObject (hConTh, INFINITE);

}

/* Клиент отсоединился или имеется запрос останова. */

FlushFileBuffers(hNamedPipe);

DisconnectNamedPipe(hNamedPipe);

 }

 /* Конец командного цикла. Освободить ресурсы; выйти из потока. */

 if (hTmpFile != INVALID_HANDLE_VALUE) CloseHandle(hTmpFile);

 DeleteFile(pThArg->TmpFileName);

 _tprintf(_T("Выход из потока номер %d\n"), pThArg->ThreadNo);

 _endthreadex(0);

}

static DWORD WINAPI Connect(LPTHREAD_ARG pThArg) {

 /* Поток соединения разрешает серверу опрос флага ShutDown. */

 ConnectNamedPipe(pThArg->hNamedPipe, NULL);

 _endthreadex(0);

 return 0;

}

BOOL WINAPI Handler(DWORD CtrlEvent) {

 /* Завершить работу системы. */

 ShutDown = TRUE;

 return TRUE;

}

Комментарии по поводу клиент-серверного процессора командной строки

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

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

• Сервер и клиенты могут выполняться либо в ответ на отдельные подсказки командной строки, либо под управлением программы JobShell (программа 6.3).

• Если во время попыток клиента соединиться с сервером все экземпляры именованного канала оказываются задействованными, то новый клиент будет находиться в состоянии ожидания до тех пор, пока другой клиент не разорвет соединение в ответ на получение команды $Quit, тем самым делая его доступным для ожидающего клиента. Возможны ситуации, когда сразу несколько новых клиентов будут одновременно пытаться создать соединение с сервером, соревнуясь между собой за право открытия доступного экземпляра; потоки, проигравшие в этой конкурентной борьбе, будут вынуждены вновь перейти в состояние ожидания.

• Каждый серверный поток выполняет синхронные операции ввода/вывода, но одни из этих потоков могут обрабатывать запросы, в то время как другие — ожидать соединения или поступления клиентских запросов.

• С учетом ограничений, свойственных именованным каналам, о чем говорилось ранее в этой главе, расширение программы на случай сетевых клиентов не составляет труда. Для этого достаточно заменить имена каналов в заголовочном файле или добавить параметр, указывающий имя сервера в командной строке клиента.

• Каждый рабочий поток сервера создает простой поток, осуществляющий соединение, который вызывает функцию ConnectNamedPipe и завершает выполнение сразу же после подключения клиента. Это позволяет организовать ожидание дескриптора потока соединения рабочим потоком с использованием конечного интервала ожидания и периодическое тестирование глобального флага завершения работы (ShutDown). Если бы рабочие потоки блокировались при выполнении функции ConnectNamedPipe, они не могли бы тестировать этот флаг, и сервер не мог бы завершить работу. По этой причине поток сервера осуществляет вызов CreateFile, используя дескриптор именованного канала, чтобы заставить поток соединения возобновиться и завершить выполнение. Альтернативным вариантом было бы использование асинхронного ввода/вывода (глава 14), что дало бы возможность связать событие с вызовом функции ConnectNamedPipe. Другие возможные варианты реализации и дополнительная информация предоставляются в комментариях к исходному тексту программы, размещенному на Web-сайте книги. Без этого решения потоки соединения могли бы никогда не завершить работу самостоятельно, что привело бы к утечке ресурсов в DLL. Этот вопрос обсуждается в главе 12.

• Существует ряд благоприятных предпосылок для усовершенствования данной системы. Например, можно предусмотреть опцию выполнения внутрипроцессного сервера (in-process server), используя библиотеку DLL, которая реализует некоторые из команд. Это усовершенствование вводится в программу в главе 12.

• Количество серверных потоков ограничивается при вызове функции WaitForMultipleObjects в основном потоке. Хотя это ограничение легко преодолимо, в данном случае система не обладает истинной масштабируемостью; как было показано в главе 10, чрезмерное увеличение количества потоков может оказать отрицательное влияние на производительность. В главе 14 для решения этой проблемы используются порты асинхронного ввода/вывода.

  • Читать дальше
  • 1
  • ...
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: