Using WebSockets for Real-Time Communication
Learn how to use WebSockets for real-time communication in web applications and ASP.NET Core.
A Simple Analogy
Imagine a phone call vs. sending letters. HTTP is like sending letters—you write one, mail it, and wait for a reply. WebSockets are like a phone call—once you connect, you can both talk instantly without waiting. The connection stays open so information flows both ways, whenever needed.
What Are WebSockets?
WebSockets is a communication protocol that provides a persistent, bi-directional connection between client and server over a single TCP connection. Unlike HTTP, which is request/response based, WebSockets allow both sides to send data at any time, making them perfect for real-time applications.
Why Use WebSockets?
- Instant updates: Data flows immediately, not on request
- Bi-directional: Server and client can both initiate communication
- Low latency: No request/response overhead
- Efficient: Single connection, not multiple HTTP requests
- Real-time features: Chat, notifications, live dashboards, multiplayer games
How WebSockets Work
- Handshake: Client sends HTTP upgrade request to server
- Connection established: Server accepts, connection becomes WebSocket
- Data exchange: Both sides send and receive frames instantly
- Persistent: Connection stays open until closed
WebSocket in ASP.NET Core
Basic WebSocket Middleware
var app = builder.Build();
app.Use(async (context, next) => {
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await HandleWebSocket(context, webSocket);
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
async Task HandleWebSocket(HttpContext context, WebSocket webSocket)
{
byte[] buffer = new byte[1024 * 4];
try
{
while (webSocket.State == WebSocketState.Open)
{
WebSocketReceiveResult result = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Text)
{
string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
await webSocket.SendAsync(
new ArraySegment<byte>(Encoding.UTF8.GetBytes($"Echo: {message}")),
WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
finally
{
webSocket.Dispose();
}
}
app.Run();
Client-Side (JavaScript)
const ws = new WebSocket('ws://localhost:5000/ws');
// Connection opened
ws.onopen = () => {
console.log('Connected');
ws.send('Hello from client!');
};
// Receive messages
ws.onmessage = (event) => {
console.log('Message from server:', event.data);
};
// Connection closed
ws.onclose = () => {
console.log('Disconnected');
};
WebSockets with SignalR (Recommended)
SignalR wraps WebSockets and provides automatic fallbacks and higher-level abstractions:
builder.Services.AddSignalR();
app.MapHub<ChatHub>("/chatHub");
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Practical Examples
- Live chat: Instant messages between users
- Multiplayer games: Real-time player positions and actions
- Stock ticker: Live price updates without polling
- Collaboration tools: Real-time document edits
- Notifications: Push alerts instantly to users
- Dashboards: Live metrics and analytics updates
Real-World Use Cases
- Customer support chat systems
- Online whiteboard and design tools
- IoT device dashboards
- Live sports or auction updates
- Collaborative editing (Google Docs-like apps)
- Online gaming platforms
- Real-time notification systems
WebSockets vs. HTTP Polling vs. Server-Sent Events
| Feature | HTTP Polling | Server-Sent Events (SSE) | WebSockets | |---------|--------------|-------------------------|-----------| | Bi-directional | Client only | Server only | Both | | Overhead | High (many requests) | Low | Very low | | Complexity | Simple | Medium | Medium | | Browser support | Excellent | Good | Excellent | | Use case | Legacy | One-way updates | Real-time chat/games |
Best Practices
- Use SignalR for most real-time needs (built-in fallbacks, easier)
- Keep WebSocket messages small for performance
- Implement proper error handling and reconnection logic
- Monitor connection count for scaling
- Use compression for large messages
- Secure with SSL/TLS (wss:// not ws://)
- Clean up connections on client disconnect
- Rate limit to prevent abuse
Related Concepts to Explore
- HTTP/2 and HTTP/3 (multiplexing, push)
- Server-Sent Events (SSE) alternative
- gRPC streaming (binary protocol)
- Message protocols (JSON, MessagePack)
- Connection pooling and scaling
- Load balancing with WebSockets
- WebSocket subprotocols
- Event-driven architecture
- Pub/Sub messaging patterns
- Real-time monitoring and observability
Summary
WebSockets enable true real-time communication between clients and servers. By maintaining a persistent connection, they eliminate the polling overhead of HTTP and unlock instant, bi-directional data flow. Whether you use raw WebSockets or the higher-level SignalR abstraction, mastering WebSockets is essential for modern, interactive web applications.