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

Ситуация:

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

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

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

Проблема:

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

Вопросы:

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

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

Ответы [ 2 ]

3 голосов
/ 12 августа 2010

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

Основной логический поток был:

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

Это действительно так.

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

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

1 голос
/ 12 августа 2010

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

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

...