Проблема:Названных трубы эффективного асинхронного дизайн
Для разработки эффективного и очень быстрая структуры клиента-сервера с именем-труба.
Текущее состояние:
У меня уже есть боевой проверенные производственные испытания рамки. Это быстро, однако он использует один поток для одного соединения с трубой, и если число клиентов несколько, число потоков может быть быстрым. Я уже использую интеллектуальный пул потоков (пул задач фактически), который может масштабироваться с потребностью.
Я уже использую OVERLAPED режим для труб, но потом блок с WaitForSingleObject или WaitForMultipleObjects так, почему я нужен один поток для каждого соединения на стороне сервера
Желаемый раствор:
Клиент отлично как есть, но на стороне сервера я хотел бы использовать один поток только для каждого запроса клиента, а не для каждого соединения. Поэтому вместо того, чтобы использовать один поток для всего жизненного цикла клиента (connect/disconnect), я бы использовал один поток для каждой задачи. Таким образом, только когда клиент запрашивает данные и не более.
Я видел пример MSDN, который использует массив структур OVERLAPED, а затем использует WaitForMultipleObjects, чтобы ждать их всех. Я нахожу этот плохой дизайн. Две проблемы, которые я вижу здесь. Сначала вам нужно поддерживать массив, который может расти довольно большой, и удаление будет дорогостоящим. Во-вторых, у вас много событий, по одному для каждого элемента массива.
Я также видел порты завершения, такие как CreateIoCompletionPort и GetQueuedCompletionStatus, но я не вижу, как они лучше.
Что мне нужно, это ReadFileEx и WriteFileEx do, они называют обратный вызов , когда операция завершена. Это истинный асинхронный стиль программирования. Но проблема в том, что ConnectNamedPipe не поддерживает это, и, кроме того, я видел, что поток должен быть в аварийном состоянии, и вам нужно вызвать некоторые из функций Ex для этого.
Итак, как решить эту проблему лучше всего?
Вот как MSDN делает это: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365603(v=vs.85).aspx
Проблема, которую я вижу с этим подходом является то, что я не могу видеть, как вы могли бы иметь 100 клиентов, подключенных на один раз, если предел WaitForMultipleObjects 64 ручки. Конечно, я могу отключить канал после каждого запроса, но идея состоит в том, чтобы иметь постоянное клиентское соединение, как и на сервере TCP, и отслеживать клиента на протяжении всего жизненного цикла, при этом каждый клиент имеет уникальные идентификационные данные и данные для конкретного клиента.
Идеальный псевдо-код должен быть таким:
repeat
// wait for the connection or for one client to send data
Result = ConnectNamedPipe or ReadFile or Disconnect;
case Result of
CONNECTED: CreateNewClient; // we create a new client
DATA: AssignWorkerThread; // here we process client request in a thread
DISCONNECT: CleanupAndDeleteClient // release the client object and data
end;
until Aborted;
Таким образом, у нас есть только один слушающий поток, который принимает подключения/отключения/Ondata события. Пул потоков (рабочий поток) обрабатывает только фактический запрос. Таким образом, 5 рабочих потоков могут обслуживать множество клиентов, которые подключены.
P.S. Мой текущий код не должен быть важен. Я кодирую это в Delphi, но его чистый WinAPI, поэтому язык не имеет значения.
РЕДАКТИРОВАТЬ:
На данный момент IOCP выглядеть решение:
порты ввода/завершения вывода обеспечивают эффективную потоковую модель для обработки множества асинхронных запросов ввода/вывода на многопроцессорной системы , Когда процесс создает порт завершения ввода-вывода, система создает связанный объект очереди для запросов, единственной целью которых является для обслуживания этих запросов. Процессы, которые обрабатывают многие параллельные запросы асинхронного ввода-вывода , могут сделать это быстрее и эффективнее с с использованием портов завершения ввода-вывода в сочетании с выделенным потоком пулом, чем путем создания потоков при получении запроса ввода-вывода ,
Также имейте в виду, что ['WaitForMultipleObject'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025) имеет ограничение в 64 дескриптора (MAXIMUM_WAIT_OBJECTS)! –
Исключения не являются дорогостоящими. Что это вообще значит? Я голосую за WFMO за перекрывающиеся структуры. Я не вижу ничего плохого в этом. Просто нужно еще одно событие в ожидающем массиве, которое остановило бы ожидание, если массив нуждается в настройке, или завершение прерывания. – Dialecticus
@Dealecticus: Деление на динамический массив является дорогостоящим. Если вы удаляете элемент посередине, вам нужно переместить все предметы, следующие за ним. Это структуры программирования 101 :) Хорошо, если у вас есть до 100 предметов, они не будут отображаться. Но я могу подключить более 100 клиентов. – Runner