Как обнаружить клиентское отключение, используя клиент / сервер с именованным каналом? - PullRequest
9 голосов
/ 04 марта 2010

Я изучаю именованные каналы и играл с примерами клиента и сервера именованных каналов из документа MSDN:

Сервер именованных каналов

Клиент Named Pipe

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

У меня вопрос: если я убью клиента (закрыв его или завершив через диспетчер задач), сможет ли серверная сторона обнаружить отключение?

Я пытался использовать GetNamedPipeHandleState (), надеясь, что он вернет ошибку, и вызов GetLastError () вернет ERROR_PIPE_NOT_CONNECTED, но это не так. Из-за того, как настроен этот сервер, мне пришлось сделать это в функции CompletedReadRoutine и создать «контролируемый» сбой. Я сделал с точкой останова на CompletedReadRoutine на сервере:

  1. запустил сервер
  2. запустил клиент
  3. отправил сообщение через клиента (достигает точки останова на сервере здесь)
  4. убил клиента
  5. Шагнул к GetNamedPipeHandleState

Вызов GetNamedPipeHandleState () успешно завершается, поэтому мне никогда не удавалось выполнить вызов GetLastError (). Когда он достигает вызова WriteFileEx, он завершается неудачно, и вызов GetLastError в этот момент возвращает ERROR_NO_DATA.

Глядя на функции конвейера, я не вижу ничего другого, что могло бы помочь здесь. Я что-то пропустил или клиентское отключение просто не обнаружено.

Единственное, о чем я могу думать, это собирать pid подключающихся клиентов (через GetNamedPipeClientProcessId) и раскручивать сторожевые потоки, чтобы проверить, живы ли они. Хотя одно лишь размышление о том, как это сделать, вызывает у меня чувство пауков.

Есть ли способ обнаружить отключенных клиентов при использовании именованных каналов?

Ответы [ 2 ]

5 голосов
/ 04 марта 2010

Не ReadFile() возвращает и ошибка и GetLastError() затем возвращает ERROR_BROKEN_PIPE?

1 голос
/ 05 июня 2016

ReadFile() + GetLastError() делают работу хорошо.Вот как их можно использовать с портами завершения ввода / вывода (моя реализация написана на python + ctypes, но идея должна быть ясна):

def connect():
    GetQueuedCompletionStatus()
    receive()

def receive():
    while True:
        ret_code = ReadFile()
        if ret_code == 0 and GetLastError() == ERROR_BROKEN_PIPE:
            # client disconnected
        GetQueuedCompletionStatus()

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

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

...