En una aplicación web asp.net core (5.0), ¿es posible mantener vivo el socket sin tener un ciclo while infinito? ( while (webSocket.State == WebSocketState.Open
) Si el bucle es la única forma de hacerlo, ¿no es muy ineficiente?
Esto es esencialmente lo que me gustaría lograr.
public class SocketController : Controller { [HttpGet] [Route("Connect")] public async Task ConnectAsync() { if (HttpContext.WebSockets.IsWebSocketRequest) { var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); SocketManager.registerSocket(User, webSocket); var outputBuffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes("pong")); await webSocket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None); } else { HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; } } }
Esto parece funcionar, pero no parece correcto.
public class SocketController : Controller { [HttpGet] [Route("Connect")] public async Task ConnectAsync() { if (HttpContext.WebSockets.IsWebSocketRequest) { var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); // stuff while (webSocket.State == WebSocketState.Open) ; } else { HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; } } }
Ejemplo mínimo para verificar el cierre del socket:
var socket = new WebSocket("wss://localhost:44331/Socket/Connect"); socket.onclose = function (err) { console.log("CLOSED"); console.error(err); };
Si elimino el ciclo, la conexión se cierra en el lado JS, en el momento en que la acción termina de ejecutarse, genera:
CLOSED { isTrusted: true, bubbles: false, cancelBubble: false, cancelable: false, code: 1006, composed: false, currentTarget: [WebSocket Object], defaultPrevented: false, eventPhase: 0, path: [], reason: "", returnValue: true, srcElement: [WebSocket Object], target: [WebSocket Object], timeStamp: 958.5999999998603, type: "close", wasClean: false }
WebSocket usa el latido del corazón de ping/pong para mantener vivo.
Una trama de ping puede servir como un keepalive o como un medio para verificar que el punto final remoto sigue respondiendo.
Pero cuando el cliente recibe un Ping, se debe enviar un Pong al servidor.
Al recibir una trama Ping, un punto final DEBE enviar una trama Pong en respuesta, a menos que ya haya recibido una trama Cerrar. DEBERÍA responder con el marco Pong tan pronto como sea práctico.
Puede usar KeepAliveInterval
para establecer la frecuencia con la que se envían marcos de "ping" al cliente para garantizar que los proxies mantengan abierta la conexión. El valor predeterminado es dos minutos.
var webSocketOptions = new WebSocketOptions() { KeepAliveInterval = TimeSpan.FromSeconds(120), }; app.UseWebSockets(webSocketOptions);
En su código, while (webSocket.State == WebSocketState.Open)
simplemente verifique el estado de websocket y no mantendrá vivo el websocket.
El servidor no es informado automáticamente cuando el cliente se desconecta debido a la pérdida de conectividad. El servidor recibe un mensaje de desconexión solo si el cliente lo envía, lo que no se puede hacer si se pierde la conexión a Internet. Si desea realizar alguna acción cuando eso suceda, establezca un tiempo de espera después de que no se reciba nada del cliente dentro de un período de tiempo determinado.