In an asp.net core (5.0) web application, is it possible to keep the socket alive without having a infinite while loop? (while (webSocket.State == WebSocketState.Open
) If the loop is the only way to do that, isn't that very inefficient?
This is essentially what I would like to achieve
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;
}
}
}
This seems to work but, it doesn't seem right
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;
}
}
}
Minimal example to check socket closing:
var socket = new WebSocket("wss://localhost:44331/Socket/Connect");
socket.onclose = function (err) {
console.log("CLOSED");
console.error(err);
};
If I remove the loop, the connection closes on the JS side, the moment the action finishes executing, output:
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 use ping/pong heartbeat to keepalive.
A Ping frame may serve either as a keepalive or as a means to verify that the remote endpoint is still responsive.
But when the client gets a Ping, a Pong must be sent back to the server
Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in response, unless it already received a Close frame. It SHOULD respond with Pong frame as soon as is practical.
You can use KeepAliveInterval
to set How frequently to send "ping" frames to the client to ensure proxies keep the connection open. The default is two minutes.
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
};
app.UseWebSockets(webSocketOptions);
In your code, while (webSocket.State == WebSocketState.Open)
just check the state of websocket and it will not keep the websocket alive.
The server is not automatically informed when the client disconnects due to loss of connectivity. The server receives a disconnect message only if the client sends it, which can't be done if the internet connection is lost. If you want to take some action when that happens, set a timeout after nothing is received from the client within a certain time window.