WebSockets & Streaming Data in .NET
Handle raw WebSocket connections for maximum control and stream large datasets efficiently with IAsyncEnumerable.
What You'll Learn
- • Accept and manage raw WebSocket connections in ASP.NET Core
- • Build a connection manager for multi-client broadcasting
- • Stream data with
IAsyncEnumerablefor memory-efficient I/O - • Choose between SignalR and raw WebSockets
🔌 Real-World Analogy
SignalR is like using a high-level messaging app — it handles reconnection, serialization, and transport for you. Raw WebSockets are like wiring your own telephone system — more work, but full control over the protocol. Use raw WebSockets when you need custom binary protocols, game networking, or integration with non-.NET clients that speak a specific protocol.
Raw WebSocket Server
ASP.NET Core has built-in WebSocket support. Accept a connection, read messages in a loop, and send responses. You manage the connection lifecycle yourself.
Raw WebSocket Echo Server
Accept WebSocket connections and echo messages back to the client.
using System.Net.WebSockets;
using System.Text;
// Program.cs — Enable WebSocket middleware
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseWebSockets(new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromSeconds(30)
});
app.Map("/ws", async (HttpContext context) =>
{
if (!context.WebSockets.IsWebSocketRequest)
{
context.Response.StatusCode = 400;
return;
}
using var ws = await context.WebSockets.AcceptWebSocketAsync()
...Multi-Client Connection Manager
For real applications, you need to track multiple connections and broadcast messages. Use a ConcurrentDictionary to safely manage connections across threads.
WebSocket Connection Manager
Track multiple clients and broadcast messages to all or specific connections.
using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
// WebSocket connection manager for multi-client scenarios
public class WebSocketManager
{
private readonly ConcurrentDictionary<string, WebSocket> _connections = new();
public string AddConnection(WebSocket socket)
{
var id = Guid.NewGuid().ToString("N")[..8];
_connections.TryAdd(id, socket);
Console.WriteLine($"Client {id} connected. Total: {_connec
...Streaming with IAsyncEnumerable
For large datasets, don't load everything into memory. IAsyncEnumerable lets you stream items one at a time, reducing memory usage and giving clients data as it's produced.
Streaming with IAsyncEnumerable
Stream sensor data from server to client without buffering the entire dataset.
using System.Runtime.CompilerServices;
using System.Text.Json;
// Server streaming with IAsyncEnumerable — great for large datasets
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
// Stream data to client as it's produced
[HttpGet("stream")]
public async IAsyncEnumerable<SensorReading> StreamReadings(
[EnumeratorCancellation] CancellationToken ct)
{
for (int i = 0; i < 100; i++)
{
if (ct.IsCancellatio
...Pro Tip
Use HttpCompletionOption.ResponseHeadersRead on the client to start processing the stream immediately instead of waiting for the entire response to download. This is critical for large or long-running streams.
Common Mistakes
- • Not disposing WebSocket connections — leads to resource leaks
- • Blocking the receive loop — use async/await consistently
- • Ignoring
CancellationToken— streams run indefinitely if client disconnects
Lesson Complete!
You've mastered raw WebSockets and streaming. Next, learn to write bulletproof unit tests with xUnit, NUnit, and MSTest.
Sign up for free to track which lessons you've completed and get learning reminders.