WebSocket in .NET

Real-Time, Two-Way Communication Over TCP/IP

Roko Kovač
3 min readDec 2, 2023


There are many techniques for achieving near-real-time communication using HTTP, such as Polling, Long Polling, Server-Sent Events, or even Webhooks.

All approaches share the same issue — they are limited to one-way communication.

In this article, we will explore WebSocket, a protocol built on top of TCP/IP that allows two-way, real-time communication and use it to implement a simple chat app in .NET 8.

WebSocket vs Server Sent Events

Just like in my previous articles, I will compare WebSocket with the closest alternative — SSE.


Both SSE and WebSockets:

  • use a single persistent TCP/IP connection
  • are supported in all modern browsers
  • allow real-time communication


Server Sent Events work with a simple HTTP request, which is limited by its Request — Response design to one-way communication.

WebSocket is a two-way (full duplex) real-time communication protocol built on top of TCP/IP. It uses an HTTP request to establish a connection (handshake), which is then upgraded to a WebSocket connection.

Unlike SSE, WebSocket also supports binary messages.

This makes it an excellent choice for cases where two-way communication is required, such as a chat app.

Establishing A WebSocket Connection

Implementing a WebSocket Server

Let’s build a simple WebSocket server in .NET 8.

If you just want the code, you can get it on my GitHub.

First, we will set up a web server and the required dependencies.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

Then, we add a simple endpoint that will check for the required headers to determine if it’s a WebSocket request, and if so, accept it and pass it onto our ChatService.

app.MapGet("/", async (HttpContext context, ChatService chatService) =>
if (context.WebSockets.IsWebSocketRequest)
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
await chatService.HandleWebSocketConnection(webSocket);
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Expected a WebSocket request");

In the ChatService, we will handle the WebSocket connection. It’s a singleton service that keeps track of all connected clients.

public class ChatService
private readonly List<WebSocket> _sockets = new();

public async Task HandleWebSocketConnection(WebSocket socket)
var buffer = new byte[1024 * 2];
while (socket.State == WebSocketState.Open)
var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), default);
if (result.MessageType == WebSocketMessageType.Close)
await socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, default);

foreach (var s in _sockets)
await s.SendAsync(buffer[..result.Count], WebSocketMessageType.Text, true, default);

While the WebSocket is open, we await the next message. If it’s a Close message, we simply close the connection. If not, we read it and write it into an allocated buffer.

We then take a slice of the buffer that contains the message and send it to all connected clients.

To keep it simple, we don’t validate message type or message size, or serialize/deserialize to domain entities, which is something you would probably want to do in a real application.

Implementing a WebSocket Client

As it’s supported by all browsers, we will use HTML and JavaScript to build a client.

<div id="messages"></div>
<input id="chatbox" >
const socket = new WebSocket('ws://localhost:5007');

socket.onmessage = function (event) {
const messages = document.getElementById("messages");
messages.innerHTML += `<p>${event.data}</p>`;

document.getElementById("chatbox").addEventListener("keyup", function(event) {
if (event.key === "Enter") {
event.target.value = "";

This simple code opens up a WebSocket connection and displays something resembling a chat application.

A Simple Chat App


I have introduced you to the WebSocket protocol and shown you how to implement a simple WebSocket server in .NET 8

For a more advanced use case, check out my chat app.

If you’re interested in .NET topics, consider subscribing.

Any thoughts? Comments are welcome!