2010-11-10 13 views
6

He seguido el Pub/sub sample using HTTP polling duplex WCF channel de Tomek Janczuk pero me he dado cuenta de que cuando un cliente se desconecta cerrando el navegador, el servicio no se da cuenta en la próxima devolución de llamada. Hubiera esperado una excepción o algo para decir que el punto final ya no estaba allí.Cómo detectar clientes de sondeo dúplex diconnected

¿Cómo se puede saber cuando un cliente se ha ido, para dejar de publicar en ese cliente?

+0

¿Los métodos de devolución de llamada son "OneWay"? Si el parámetro IsOneWay fuera falso en el atributo OperationContract, ¿el servidor detectará los tiempos de espera excedidos? (Comentando no responder, porque no estoy seguro) –

Respuesta

3

Parece que hay una solución insatisfactoria, aunque simple: si la devolución de llamada del cliente expira, no la vuelva a llamar.

En mi sistema también he implementado una llamada manual de "comprobación" - cada n segundos el servidor llama a un método sin parámetros sobre el canal de devolución de llamada para cada cliente registrado, solo para ver si el cliente aún está allí. Estoy empezando a preguntarme si realmente fue una buena idea: tengo un problema nuevo donde el tiempo de espera de devolución de llamada sigue ocurriendo porque suspendí al cliente en el depurador.

+0

En mi prueba inicial, el problema es que no obtengo el tiempo de espera. Estoy jugando con un enfoque similar al tuyo, excepto al revés. Los clientes "hacen ping" al servidor y si el servidor no los ha escuchado en un período de tiempo determinado, están fuera de la lista, lo que creo es similar a la administración de la sesión asp.net. –

+0

@Ralph - Estaba usando netTcpBinding (era un cliente grueso, no Silverlight). Quizás el enlace PollingDuplexHttp simplemente no excede el tiempo de espera, en cuyo caso la solución que ha descrito sería la única opción. –

5

Para saberlo seguro: imposible.

Cuando se cierra una conexión TCP (subyacente a una llamada HTTP), se envía un mensaje TCP especial al servidor - paquete FIN. Aunque HTTP no tiene estado, la conexión TCP subyacente es con estado y con keep alive, la conexión TCP subyacente generalmente permanece abierta. Si el cliente se elimina, la conexión TCP se cierra y normalmente se envía un mensaje al servidor. Pero si se bloquea o su red se desconecta, no tendría tiempo para hacerlo. Entonces, en una palabra, nunca puedes estar seguro.

Here para obtener más información.

+0

En una palabra, me gusta esta respuesta. :-) –

3

Es difícil, casi imposible (causa de capacidades dúplex SL limitadas). hemos implementado una lista de usuarios en nuestro servicio, y hemos agregado una propiedad "IsDisconnected" y LastCommunicationTime, una vez que el servicio WCF obtiene un tiempo de espera cuando intenta agregar un mensaje en Outgoing-Message-Queue, y falla, y arroja una excepción de tiempo de espera. marcamos "IsDisconnecte = true" y la próxima vez no intentemos enviarle el mensaje a ese usuario.

Otro hilo sigue mirando eso y si se da cuenta de que LastCommunicationTime ha sido excedido por un valor de tiempo e IsDisconnected = true, elimina al usuario de la lista, a menos que el mismo usuario intente conectarse nuevamente dentro de este tiempo período (que identificamos por su UserId).

Hay tantas cosas que hicimos manualmente para manejar este problema, ya que estaba haciendo que el servicio WCF estuviera tan ocupado.

+0

Terminé adoptando un patrón muy similar. –

+0

Pero recuerde: Esto crea otro problema, el servidor es demasiado inteligente ahora y siempre está listo para expulsar a los usuarios :), ¿qué pasa con los usuarios que no se han ido pero están muy silenciosos pero de alguna manera su llamada de conexión ha fallado? el canal de su cliente ha sido criticado, en ese caso tendrían que abrir el canal una vez más, lo que les da una nueva ID de sesión, y ese canal sería nuevo para el servidor.Entonces, al registrarse en el servidor una vez agian, el servidor debe eliminar el antiguo elemento de usuario de la Lista y agregar uno nuevo/O actualizarlo con uno nuevo (ClientCallback Channel es muy imp) –

+0

cuando el canal del Cliente se culpa causa de "cuando se hace- solicitud de conexión obtiene un error ". el servidor no lo sabe al instante. Y Client.ChannelFaulted dispara en el servidor cuando excede serverPooltimeout. Que es un "Movimiento ciego del servicio WCF", si sabes a lo que me refiero. Aunque no estoy seguro acerca de serverPooltimeout en ese caso al 100%, sinceramente, me pareció un poco aleatorio. –

1

Me enfrenté a este problema y creé un hilo que elimina clientes desconectados con el siguiente código. Funciona bien, pero deja al cliente desconectado de la lista de clientes después de 10-15 minutos (lo que estaba bien para mí).

new Thread(new ThreadStart(() => 
    { 
     while (SilverlightClients != null) 
     { 
       lock (SilverlightClients) 
       { 
        SilverlightClients = SilverlightClients.Where(d => (d.Callback as IContextChannel).State != CommunicationState.Opened).ToList(); 
       } 

      Thread.Sleep(1000); 
     } 
    })) { Name = "Thread Remove Disconnected Clients" }.Start(); 
Cuestiones relacionadas