2010-03-03 15 views
8

estoy aprendiendo sobre canalizaciones con nombre y estaba jugando con los ejemplos de cliente y servidor de canalización con nombre del documento de MSDN:¿Cómo detectar una desconexión del cliente utilizando un cliente/servidor de canalización con nombre?

Named Pipe Server

Named Pipe Client

he modificado el cliente para que pueda escribir mensajes a la consola y hacer que se envíen al servidor donde muestra el mensaje y envía una respuesta. Básicamente, agregué un bucle que se inicia después de la llamada SetNamedPipeHandleState() y finaliza antes de la llamada CloseHandle() (es decir, el abrir y cerrar pasa fuera del bucle, entonces estoy usando el mismo manejador de tubería dentro del bucle).

Mi pregunta es, si elimino al cliente (cerrándolo o finalizándolo a través del Administrador de tareas) ¿hay alguna forma para que el lado del servidor detecte la desconexión?

He intentado usar GetNamedPipeHandleState() esperando que devuelva el error y una llamada a GetLastError() devolverá ERROR_PIPE_NOT_CONNECTED, pero ese no fue el caso. Debido a la forma en que está configurado este servidor, tuve que hacer esto en la función CompletedReadRoutine y crear una falla "controlada". Lo que hice fue, con un punto de interrupción en el CompletedReadRoutine en el servidor:

  1. iniciado el servidor
  2. inició el cliente
  3. envió un mensaje a través del cliente (da en el punto de interrupción en el servidor aquí)
  4. mataron al cliente
  5. entramos por la GetNamedPipeHandleState

la llamada a GetNamedPipeHandleState() devuelve el éxito completamente así que nunca tuve que hacer la llamada GetLastError(). Cuando llega a la llamada WriteFileEx falla y una llamada a GetLastError en ese punto devuelve un ERROR_NO_DATA.

En cuanto a las funciones de tubería, no veo nada más que pueda ayudar aquí. Me falta algo o es una desconexión del cliente simplemente no detectable.

La única otra cosa en la que puedo pensar es en recopilar los pid de los clientes que se conectan (a través de GetNamedPipeClientProcessId) y girar hilos de vigilancia para comprobar si todavía están vivos. Sin embargo, solo pensar en hacer eso desencadena mi sentido spidey.

¿Hay alguna forma de detectar clientes desconectados al usar canalizaciones con nombre?

Respuesta

5

¿No devuelve ReadFile() error y GetLastError() y luego devuelve ERROR_BROKEN_PIPE?

+0

Solo si mato al cliente con mucho cuidado usando puntos de interrupción en el servidor para poder matar al cliente en un piont específico en la lógica del servidor. Por ejemplo, si inicio el cliente y lo elimino inmediatamente después de la conexión inicial, pero antes de la primera vez que el servidor llama a ReadFileEx, entonces sí obtengo ERROR_BROKEN_PIPE. El problema es que el servidor espera en la llamada a WaitForSingleObjectEx. Si el lado del cliente falla, no escribe ni lee desde esa instancia previamente conectada a la tubería. –

+3

Realmente no creo que esas muestras sean tan buenas como un ejemplo de cómo hacer las cosas ... Personalmente, siempre tendría una lectura superpuesta pendiente en la tubería, de esa manera siempre debería recibir una notificación cuando el cliente se vaya. .. –

+0

Te escucho y estoy de acuerdo en que los ejemplos que tengo no son lo que debería buscar en la forma en que me gustaría que funcione la comunicación. Gracias por tu contribución. –

1

ReadFile() + GetLastError() hacen bien el trabajo. Aquí está la forma en que se pueden utilizar con I/O Puertos de terminación (mi aplicación es en Python + ctypes, pero la idea debe ser claro):

def connect(): 
    GetQueuedCompletionStatus() 
    receive() 

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

Estamos a la espera de un paquete de finalización, y cuando una conecta el cliente , cambiamos al ciclo principal. En el ciclo principal leemos el conducto y verificamos si el cliente se ha desconectado al mirar el código de retorno ReadFile() y GetLastError(). Por otra parte, esperaremos un paquete de finalización.

Un cliente puede desconectarse en cualquier etapa. El paquete de finalización se pondrá en cola y obtendremos ERROR_BROKEN_PIPE.

+0

¿Qué lenguaje de programación es este? Se parece un poco a Python, pero AFAIK 'winapi' es solo C, C++, C# y Visual Basic. – wizzwizz4

+0

Sí, esto es Python, pero puede llamar a las funciones de winapi usando la biblioteca ctypes. Un mecanismo que permite esto se llama FFI: https://en.wikipedia.org/wiki/Foreign_function_interface – wombatonfire

Cuestiones relacionadas