Overview
- WebSocket is a protocol that enables two-way persistent communication channels over TCP connections.
- Use WebSockets to work directly with a socket connection.
- SignalR provides a richer app model for real-time functionality.
- If WebSockets is used, features that SignalR provides must be provided by the developer:
- Support for a broader range of browser versions by using automatic fallback to alternative transport methods.
- Automatic reconnection when a connection drops.
- Support for clients calling methods on the server or vice versa.
- Support for scaling to multiple servers.
- Add the
WebSockets
middleware in the Configure
method:
app.UseWebSockets();
- The following settings can be configured:
KeepAliveInterval
: How frequently to send "ping" frames to the client to ensure proxies keep the connection open.
ReceiveBufferSize
: The size of the buffer used to receive data.
- Advanced users may need to change this for performance tuning based on the size of the data.
app.UseWebSockets(new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 4 * 1024
});
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await Echo(context, webSocket);
}
else context.Response.StatusCode = 400;
}
else await next();
});
Send & Receive Messages
- The
AcceptWebSocketAsync
method upgrades the TCP connection to a WebSocket connection and provides a WebSocket
object.
- Use the
WebSocket
object to send and receive messages.
- The code shown earlier that accepts the WebSocket request passes the
WebSocket
object to an Echo
method.
- The code receives a message and immediately sends back the same message. Messages are sent and received in a loop until the client closes the connection:
private async Task Echo(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count),
result.MessageType, result.EndOfMessage, CancellationToken.None);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
- When accepting the WebSocket connection before beginning the loop, the middleware pipeline ends. Upon closing the socket, the pipeline unwinds.
- That is, the request stops moving forward in the pipeline when the WebSocket is accepted.
- When the loop is finished and the socket is closed, the request proceeds back up the pipeline.