tutorial net mvc example c# signalr signalr-hub signalr.client

c# - mvc - La mejor práctica para volver a conectar SignalR 2.0.NET cliente al servidor hub



signalr tutorial (4)

Estoy usando SignalR 2.0 con el cliente .NET en una aplicación móvil, así que necesito manejar varios tipos de desconexiones. A veces, el cliente de SignalR se vuelve a conectar sin mi ayuda, y algunas veces tengo que volver a conectar llamando nuevamente a HubConnection.Start (). (Puesto que SignalR se reconecta mágicamente de vez en cuando, me pregunto si me falta una función o ajuste de configuración)

¿Cuál es la mejor manera de configurar un cliente que se reconecta automáticamente? He visto ejemplos de javascript que manejan el evento Closed () y luego Connect después de n segundos. ¿Hay algún enfoque recomendado?

He leído la documentación y varios artículos sobre la duración de las conexiones de SignalR, pero todavía no tengo claro cómo manejar la reconexión del cliente.

¡Gracias!



Desde que OP solicitó un cliente .NET (una implementación winform a continuación),

private async Task<bool> ConnectToSignalRServer() { bool connected = false; try { Connection = new HubConnection("server url"); Hub = Connection.CreateHubProxy("MyHub"); await Connection.Start(); //See @Oran Dennison''s comment on @KingOfHypocrites''s answer if (Connection.State == ConnectionState.Connected) { connected = true; Connection.Closed += Connection_Closed; } return connected; } catch (Exception ex) { Console.WriteLine("Error"); return false; } } private async void Connection_Closed() { if(!IsFormClosed) // A global variable being set in "Form_closing" event of Form, check if form not closed explicitly to prevent a possible deadlock. { // specify a retry duration TimeSpan retryDuration = TimeSpan.FromSeconds(30); while (DateTime.UtcNow < DateTime.UtcNow.Add(retryDuration)) { bool connected = await ConnectToSignalRServer(); if (connected) return; } Console.WriteLine("Connection closed") } }


Finalmente me di cuenta de esto. Esto es lo que aprendí desde que comencé esta pregunta:

Antecedentes: estamos construyendo una aplicación iOS con Xamarin / Monotouch y el cliente .NET SignalR 2.0.3. Estamos utilizando los protocolos predeterminados de SignalR, y parece estar usando SSE en lugar de sockets web. Todavía no estoy seguro de si es posible usar conectores web con Xamarin / Monotouch. Todo está alojado en los sitios web de Azure.

Necesitábamos que la aplicación se reconectara rápidamente a nuestro servidor SignalR, pero seguíamos teniendo problemas donde la conexión no se reconectaba por sí sola, o la reconexión tardaba exactamente 30 segundos (debido a un tiempo de espera del protocolo subyacente).

Hubo tres escenarios que terminamos probando:

Escenario A: conectando la primera vez que se cargó la aplicación. Esto funcionó impecablemente desde el primer día. La conexión se completa en menos de .25 segundos incluso a través de conexiones móviles 3G. (suponiendo que la radio ya está encendida)

Escenario B: reconexión al servidor SignalR después de que la aplicación estuvo inactiva / cerrada durante 30 segundos. En este escenario, el cliente SignalR eventualmente se volverá a conectar al servidor por sí mismo sin ningún trabajo especial, pero parece esperar exactamente 30 segundos antes de intentar reconectarse. (demasiado lento para nuestra aplicación)

Durante este período de espera de 30 segundos, intentamos llamar a HubConnection.Start () que no tuvo ningún efecto. Y llamar a HubConnection.Stop () también lleva 30 segundos. Encontré un error relacionado en el sitio de SignalR que parece estar resuelto , pero todavía tenemos el mismo problema en v2.0.3.

Escenario C: reconexión al servidor SignalR después de que la aplicación estuvo inactiva / cerrada durante 120 segundos o más. En este escenario, el protocolo de transporte SignalR ya ha agotado el tiempo de espera para que el cliente nunca vuelva a conectarse automáticamente. Esto explica por qué el cliente algunas veces, pero no siempre, se reconectaba por sí mismo. La buena noticia es que llamar a HubConnection.Start () funciona casi instantáneamente como en el escenario A.

Así que me tomó un tiempo darme cuenta de que las condiciones de reconexión eran diferentes según si la aplicación se cerró durante 30 segundos frente a más de 120 segundos. Y aunque los registros de seguimiento de SignalR iluminan lo que sucede con el protocolo subyacente, no creo que haya una forma de manejar los eventos de nivel de transporte en el código. (el evento Cerrado () se dispara después de 30 segundos en el escenario B, al instante en el escenario C, la propiedad de estado dice "Conectado" durante estos períodos de espera de reconexión, no hay otros eventos o métodos relevantes)

Solución: la solución es obvia. No estamos esperando que SignalR haga su magia de reconexión. En cambio, cuando la aplicación se activa o cuando se restablece la conexión de red del teléfono, simplemente estamos limpiando los eventos y eliminando la referencia del HubConnection (no podemos eliminarlo porque lleva 30 segundos, con suerte la recolección de basura se encargará de ello) ) y creando una nueva instancia. Ahora todo está funcionando bien. Por alguna razón, pensé que deberíamos reutilizar una conexión persistente y reconectar en lugar de simplemente crear una nueva instancia.


Puede intentar invocar el método del servidor desde su Android antes de volver a conectar el estado para evitar problemas de reconexión mágica.

SignalR Hub C #

public class MyHub : Hub { public void Ping() { //ping for android long polling } }

En Android

private final int PING_INTERVAL = 10 * 1000; private boolean isConnected = false; private HubConnection connection; private ClientTransport transport; private HubProxy hubProxy; private Handler handler = new Handler(); private Runnable ping = new Runnable() { @Override public void run() { if (isConnected) { hubProxy.invoke("ping"); handler.postDelayed(ping, PING_INTERVAL); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); System.setProperty("http.keepAlive", "false"); ..... ..... connection.connected(new Runnable() { @Override public void run() { System.out.println("Connected"); handler.postDelayed(ping, PING_INTERVAL); }); }