Подтвердить что ты не робот

Блокировка блокировки ReadFile() - именованная труба (Windows API)

Чтобы упростить, это ситуация, когда NamedPipe SERVER ожидает, что КЛИЕНТ NamedPipe будет писать в трубу (используя WriteFile())

В Windows API, который блокируется, является ReadFile()

Сервер создал синхронный канал (без перекрытия ввода-вывода) с включенной блокировкой

Клиент подключился, и теперь сервер ждет некоторых данных.

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

Между тем происходит событие (например, пользовательский ввод), и NamedPipe SERVER должен выполнить другой код, который он не может сделать, пока блокирует ReadFile().

В этот момент я должен упомянуть, что клиент NamedPipe не является моим приложением, поэтому я не контролирую его. Я не могу заставить его отправить несколько байтов, чтобы разблокировать сервер. Он просто сидит и не посылает никаких данных. Поскольку я не контролирую реализацию Клиента, я ничего не могу изменить с этой целью.

Одним из решений было бы создать отдельный поток, в котором выполняются все операции ReadFile(). Таким образом, когда событие происходит, я могу просто обработать код. Проблема в том, что для события также требуется отдельный поток, поэтому теперь у меня есть два дополнительных потока для каждого экземпляра этого сервера. Поскольку это должно быть масштабируемым, это нежелательно.

Из другого потока, который я пробовал, звонил

 DisconnectNamedPipe()

и

 CloseHandle()

оба они не вернутся (пока клиент не напишет в трубку.)

Я не могу подключиться к одному и тому же каналу и написать несколько байтов, потому что:

"Все экземпляры именованного канала имеют одинаковое имя канала, но каждый экземпляр имеет его собственные буферы и дескрипторы и предоставляет отдельный канал для клиента/сервера связь ".

http://msdn.microsoft.com/en-us/library/aa365590.aspx

Мне нужен способ подделать его, поэтому вопрос стоимостью $64 000 долларов:

Как я могу разбить блокировку ReadFile()?

4b9b3361

Ответ 1

Попробуйте это перед ReadFile:

BOOL WINAPI PeekNamedPipe(
  __in       HANDLE hNamedPipe,
  __out_opt  LPVOID lpBuffer,
  __in       DWORD nBufferSize,
  __out_opt  LPDWORD lpBytesRead,
  __out_opt  LPDWORD lpTotalBytesAvail,
  __out_opt  LPDWORD lpBytesLeftThisMessage
);

if(TotalBytesAvail > 0)
  ReadFile(....);

AV--

Ответ 2

Взгляните на CancelSynchronousIo

Отмечает ожидающий синхронный ввод-вывод операции, выпущенные указанный поток отменен.

И CancelIo/CancelIoEx:

Отменить все ожидающие асинхронные операции ввода-вывода выполните следующие действия:

CancelIo - эта функция отменяется только операции, выданные вызывающим thread для указанного дескриптора файла.

CancelIoEx - эта функция отменяет все операции, выпущенные потоками для указанный дескриптор файла.

Ответ 3

Майк,

Вы не можете отменить синхронный ReadFile. Но вы можете переключиться на асинхронные (перекрывающиеся) операции. Делая это, вы можете реализовать довольно масштабируемую архитектуру.

Возможный алгоритм (просто идея):

  • Для каждого нового клиентского вызова ReadFile
  • WaitForMultipleObjects, где ручки перекрываются. hEvent + your пользовательские события
  • Итерация по сигнальным событиям и планирование их выполнения потоками из пула потоков.

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

Ответ 4

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

Никогда в моей карьере я не обнаружил, что "больше потоков" == "менее масштабируемо". Сколько из этих "серверных" экземпляров у вас есть?

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

Ответ 6

Что происходит, так это исходящий канал сервера остается открытым, ожидая соединения, пока ваш клиент пытается подключиться к входящему каналу сервера (который больше не существует). Что вам нужно сделать, это вымыть ваш исходящий канал в чтобы вернуться к вашему входящему. Вы можете выполнить очистку на стороне клиента, прочитав файл (не забудьте установить соединение для подключения, потому что там есть "рукопожатие", и оно никогда не будет работать в первый раз)