Именованные каналы: много клиентов. Как быть осторожным с созданием потоков? Пул потоков?

Ситуация:

Я использую именованные каналы в Windows для IPC, используя C ++.

Сервер создает экземпляр именованного канала через CreateNamedPipe и ожидает подключения клиентов через ConnectNamedPipe.

Каждый раз, когда клиент вызывает CreateFile для доступа к именованному каналу, сервер создает поток, используя CreateThread для обслуживания этого клиента. После этого сервер повторяет цикл, создавая экземпляр канала через CreateNamedPipe и ожидая следующего клиента через ConnectNamedPipe и т. Д.

Проблема:

Каждый клиентский запрос запускает CreateThread на сервере. Если клиенты приходят в ярость, будет много вызовов CreateThread.

Вопросы:

Q1: Можно ли повторно использовать уже созданные потоки для обслуживания будущих клиентских запросов? Если это возможно, как мне это сделать?

Q2: Может ли пул потоков помочь в этой ситуации?


person moog    schedule 12.08.2010    source источник


Ответы (2)


Сегодня я написал сервер именованного канала, используя порты IOCompletion, просто чтобы посмотреть, как это сделать.

Базовый логический поток был следующим:

  • Я создал первый именованный канал через CreateNamedPipe
  • Я создал основной объект порта завершения ввода-вывода, используя этот дескриптор: CreateIoCompletionPort
  • Я создаю пул рабочих потоков - как пустяк, CPU x2. Каждый рабочий поток вызывает GetQueuedCompletionStatus в цикле.
  • Затем вызывается ConnectNamedPipe, передавая перекрывающуюся структуру. Когда этот канал подключается, возвращается один из вызовов GetQueuedCompletionStatus.
  • Затем мой основной поток присоединяется к пулу рабочих, также вызывая GetQueuedCompletionStatus.

Вот и все на самом деле.

Каждый раз, когда поток возвращается из GetQueuedCompletionStatus, это связано с тем, что связанный канал был подключен, прочитал данные или был закрыт. Каждый раз, когда канал подключается, я немедленно создаю неподключенный канал для приема следующего клиента (вероятно, должно иметь более одного ожидания одновременно) и вызываю ReadFile в текущем канале, передавая перекрывающуюся структуру - гарантируя, что по мере поступления данных GetQueuedCompletionStatus будет Расскажи мне об этом.

Есть несколько раздражающих крайних случаев, когда функции возвращают код ошибки, но GetLastError () работает успешно. Поскольку функция "завершилась неудачно", вы должны немедленно обработать успех, поскольку статус завершения в очереди не был опубликован. И наоборот (и я верю, что Vista добавляет API для «исправления» этого), если данные доступны немедленно, перекрывающиеся функции могут возвращать успех, но ТАКЖЕ публикуется статус завершения в очереди, поэтому будьте осторожны, чтобы в этом случае не обрабатывать данные дважды.

person Chris Becke    schedule 12.08.2010

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

Vista / Windows 2008 предоставляют абстракцию пула потоков.

person carlsborg    schedule 12.08.2010
comment
Спасибо за рекомендацию - порты завершения ввода-вывода выглядят многообещающе. Я прочитаю об этом подробнее. (Я ориентируюсь на XP и выше). - person moog; 12.08.2010