Although SignalR and WebSockets are not comparable one-on-one, there are some advantages to using .NET SignalR over plain WebSockets.
Unlike traditional request-response models, where clients send requests to the server to get information, real-time applications enable users to receive information as it happens without requiring a refresh. From chat apps, maps, and games to monitoring apps and dashboards to collaborative apps, real-time functionality has become fundamental to today’s software development.
The WebSocket Protocol
WebSocket is a communication protocol that enables simultaneous two-way communication over one long-lived TCP connection.
To initiate a WebSocket connection, the client and server exchange an opening HTTP handshake. Once they connect, communication upgrades from HTTP protocol to WebSocket using the HTTP Upgrade header. After finishing the upgrade request, the client and server can exchange messages over a WebSocket connection without the overhead of HTTP headers.
Finally, the lifecycle of the WebSocket connection ends, and the connection is closed by a closing handshake.

WebSocket Protocol Key Characteristics
It is a protocol: Stating the obvious, Websocket is actually a standardized protocol that you can use across different operating systems and programming languages, ensuring broad compatibility and interoperability.
Persistent connection: Once the WebSocket connection is established, it remains open using a persistent connection, improving real-time communication by eliminating the need for repeated reconnections.
Full duplex: Communicating in full-duplex enables two-way data exchange without waiting for the other party to finish the transmission.
WebSocket Protocol Key Limitations
Complexity: Implementing WebSocket applications requires manual connection lifecycle management, message framing, and error handling. WebSocket connections don’t automatically recover when terminated; you must handle them manually. That makes them more complex to implement than using SignalR, which handles connections automatically.
Limited support and lack of fallback mechanisms: Even though many modern browsers and platforms support WebSockets, certain environments still block or restrict WebSocket connections, leading to connectivity issues or connections not establishing at all.
.NETs SignalR
ASP .NET Core SignalR is a library that simplifies the addition of real-time functionality to applications.
For client-server communication, SignalR uses the SignalR Hubs API. This high-level pipeline allows clients and servers to communicate directly. First, the messages arrive at the hub and then are delivered to the clients or used by the server.

SignalR Key Characteristics
Automatic fallback: Under the hood, SignalR uses WebSocket as the main protocol. It is the optimal transport option because it allows full duplex communication between client and server, makes the most efficient use of server memory, and has the lowest latency.
However, to ensure a graceful callback if a WebSocket connection is not possible, SignalR uses Server-Sent Events or Long Polling based on the capabilities of the server and client. By prioritizing the best available transport method and seamlessly falling back to alternatives when necessary, SignalR ensures that real-time functionality remains effective and resilient.
When both server and client support WebSocket connection:
Long Polling and Server-Sent Events reduce the server’s transport options to simulate an environment without WebSocket.
app.MapHub<ChatHub>("/chatHub", options =>
{
options.Transports =
Microsoft.AspNetCore.Http.Connections.HttpTransportType.ServerSentEvents |
Microsoft.AspNetCore.Http.Connections.HttpTransportType.LongPolling;
}
);
With this WebSocket restriction, the client falls back to Server-Sent Events:
Stateful reconnect: When clients experience a temporary network connection loss or a short disconnection when switching network connections, SignalR’s stateful reconnect reduces their perceived downtime.
You can achieve this by temporarily buffering data on the client and server, acknowledging messages received by both client and server, recognizing when the connection is returning, and replaying the messages that were sent while the connection was down.
Enabling stateful reconnect at server hub endpoint:
app.MapHub<ChatHub>("/chatHub", options =>
{
options.AllowStatefulReconnects = true;
});
Enabling stateful reconnect with the client:
var connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.configureLogging(signalR.LogLevel.Debug)
.withStatefulReconnect()
.build();
Broadcasting to all clients: One of its powerful features is simultaneously broadcasting messages to all connected clients or specific groups of clients. This is particularly useful for applications that must keep all users updated with the latest information.
SignalR Key Limitations
Data integrity: SignalR offers a rather weak Quality of Service. If delivering messages in the correct order and without loss is critical for your application, you would have to implement that manually. You can develop mechanisms to ensure robust messaging by adding sequencing information to messages.
Flexibility: SignalR is an abstraction over WebSocket, so it provides less flexibility. The main goal is to offer a solution covering most of the use cases. The configurable options do exist, but by the time you have them configured and ready, you may as well have used WebSocket directly, as it offers more flexibility.
Performance: Since SignalR messages contain slightly bigger overhead, it can create additional latency and lower message throughput than WebSocket. Due to the lightweight protocol, WebSocket connections consume fewer resources than SignalR. Here is an example of response time for messages in the SignalR and WebSocket apps.
Response time SignalR:
Response time WebSocket:
Websocket and SignalR Comparison
Key Similarities
Websocket and SignalR share several key similarities:
- they enable real-time communication between clients and servers,
- they both provide bidirectional communication, allowing data to be simultaneously sent and received by server and client,
- they establish persistent connections, compared to traditional HTTP request/response cycles,
- they are both designed for efficient and low-latency data transfer.
Key Differences
Level of abstraction: WebSocket is a low-level transport protocol that provides a simple and minimal API. It is easy to customize, but developers manage connection states, reconnections, and other low-level details.
SignalR is a library that abstracts much of the complexity. It deals with connection management, fallbacks to other transports, and broadcasting to clients.
Transport fallbacks:If WebSocket connections are not supported or are client or server block them, the real-time connection will not be established because WebSocket does not provide fallback mechanisms.
SignalR supports not only WebSocket protocol but also Server-Sent Events and Long Polling and chooses protocols based on server and client capabilities.
Language and platform support:WebSocket is supported by most modern browsers and various server implementations across different programming languages, while SignalR offers client libraries for Java and JavaScript, but the server library is compatible with .NET only.
Chat Application Example
Using WebSocket
Let’s see how the WebSocket connection is handled.
async Task HandleWebSocketConnection(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
var serverMsg = Encoding.UTF8.GetBytes($"Server: {message}");
// Broadcast the message to all connected clients
foreach (var socket in webSocketConnections.Keys)
{
if (socket.State == WebSocketState.Open)
{
await socket.SendAsync(new ArraySegment<byte>(serverMsg, 0,
serverMsg.Length), result.MessageType,
result.EndOfMessage, CancellationToken.None);
}
}
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer),
CancellationToken.None);
}
webSocketConnections.TryRemove(webSocket, out _);
await webSocket.CloseAsync(result.CloseStatus.Value,
result.CloseStatusDescription, CancellationToken.None);
}
The HandleWebSocketConnection method handles an individual WebSocket connection. It receives messages from the client, processes them, and broadcasts them to all connected clients. It continues to do so until the client closes the connection, at which point it removes the WebSocket connection from the list of active connections and closes it.
Using SignalR
Let’s see how to create the same chat application using SignalR.
namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}
The ChatHub class inherits from the SignalR Hub class, which manages connections, groups, and messaging. The SendMessage method is called from the client and sends a message to all clients. On the client side, a connection object with a handler sends and receives messages from the hub.
This simple example shows that WebSocket requires more code and explicit management of connections and message handling, while SignalR simplifies the process with high-level abstractions. It handles adding new connections, message broadcasting, and maintaining the list of connected clients internally.
The choice between SignalR and WebSocket
The choice between using SignalR and WebSocket depends on your application’s requirements and the flexibility you need. If you need to control and customize your connections, WebSocket is a better choice. It allows you to build a completely custom messaging system.
For example, you can customize it to use protocol buffers in order to minimize message size and maximize transmission efficiency, integrate authorization during the handshake, or prioritize messages by tagging them with priority levels.
On the other hand, SignalR might be a better fit for more complex scenarios since it handles complexities like automatic reconnections, broadcasting messages, or transport fallbacks.
The ability to fall back to other communication protocols like Server-Sent Events and Long Polling ensures communication in environments where WebSocket is not supported. It saves you time in handling connection issues and provides you with common messaging features out of the box.



