Library / SDK
sta/websocket-sharp avatar
sta/websocket-sharp

websocket-sharp: both ends of an RFC 6455 connection in one C# assembly

A C# implementation of the WebSocket protocol client and server

6,078 stars1,680 forksC#MIT

At a glance

What is it?
websocket-sharp puts an RFC 6455 client, a server, per-message compression, and HTTP proxy support into one MIT assembly. Getting it is the awkward part: a prerelease NuGet package, a dll you reference by hand, and a build written down only as a MonoDevelop menu click.
Who is it for?
Take websocket-sharp when both ends of the connection are .NET and you can live with the install. Check first that your runtime is covered by .NET Framework 3.5 or later, then pin the exact prerelease package version you tested, because the repository publishes no GitHub releases and its last push was on 2026-10-11.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • sta/websocket-sharp6,078 ★ · +1
Star history
Repository2026-09-232026-11-14
sta/websocket-sharp6.1k6.1k

1 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

MonoDevelop builds one websocket-sharp.dll, and no build command is written down

Everything ships as one file. websocket-sharp is built as a single assembly, websocket-sharp.dll, and the project is developed with MonoDevelop: open websocket-sharp.sln, run build for the websocket-sharp project, and take any of the build configurations, for example Debug. That is the whole build story as far as it is written down. There is no msbuild line and no dotnet build invocation for a build server to call. Among the top-level entries (.gitignore, Example/, Example2/, Example3/, LICENSE.txt, README.md, websocket-sharp.sln, websocket-sharp/, websocket-sharp_icon.png, websocket-sharp_logo.png) no test project and no CI configuration appear, so unattended builds are yours to arrange. The target is .NET Framework 3.5 or later, or a compatible environment such as Mono.

Install-Package WebSocketSharp -Pre pulls a prerelease, not a tagged release

Two ways in, each with a cost. The self build route leaves you owning the compile: take the dll from your build output, for example /path/to/websocket-sharp/bin/Debug/websocket-sharp.dll, and add it to the library references of your project. A Unity project adds that same dll to any folder inside the Unity Editor, Assets/Plugins for instance. The NuGet route is a single line in the Package Manager Console.

code
PM> Install-Package WebSocketSharp -Pre

The -Pre flag is the point. The package sits on the NuGet Gallery as a prerelease version, and the repository has no GitHub releases, so there is no tagged artifact to download and no stable channel to aim a production project at. Either way you end up deciding which build of the library ships with you.

A first client program hooks OnMessage, then calls ws.Connect () and ws.Send ()

The opening sample is a complete console program: create the WebSocket in a using block, subscribe to OnMessage, connect, send one string.

csharp
using System;
using WebSocketSharp;

namespace Example
{
  public class Program
  {
    public static void Main (string[] args)
    {
      using (var ws = new WebSocket ("ws://dragonsnest.far/Laputa")) {
        ws.OnMessage += (sender, e) =>
                          Console.WriteLine ("Laputa says: " + e.Data);

        ws.Connect ();
        ws.Send ("BALUS");
        Console.ReadKey (true);
      }
    }
  }
}

The ordering is deliberate. Create the instance with the URL, attach the handlers, then connect, because no message can arrive before the connection exists. The using block is not decoration either: WebSocket inherits System.IDisposable, and control leaving the block closes the connection with status code 1001.

OnMessage splits text from binary, and pings stay silent until EmitOnPing is set

One event carries messages, but not through one property. A WebSocketSharp.MessageEventArgs instance arrives as e. The e.Data property returns a string for text data, while e.RawData returns a byte[] for binary data, and the sample routes between them with flags.

csharp
if (e.IsText) {
  // Do something with e.Data.
  ...

  return;
}

if (e.IsBinary) {
  // Do something with e.RawData.
  ...

  return;
}

Pings are the sharp edge. They reach OnMessage only after you set ws.EmitOnPing = true, and then you test e.IsPing inside the handler.

csharp
ws.EmitOnPing = true;
ws.OnMessage += (sender, e) => {
                  if (e.IsPing) {
                    // Do something to notify that a ping has been received.
                    ...

                    return;
                  }
                };

Until that property is flipped, a keepalive frame from the peer produces no callback, which reads like an idle connection.

Send takes four payload shapes, and the async form hands back an Action<bool>

WebSocket.Send is overloaded across four payload types: WebSocket.Send (string), WebSocket.Send (byte[]), WebSocket.Send (System.IO.FileInfo), and WebSocket.Send (System.IO.Stream, int). The FileInfo overload sends a file, and the Stream overload pairs the stream with an explicit length. The synchronous call site is one line.

csharp
ws.Send (data);

The asynchronous form takes a completion callback, and that callback is an Action<bool> delegate, so the send outcome reaches your code as a delegate argument rather than a return value.

csharp
ws.SendAsync (data, completed);

ConnectAsync () and CloseAsync () are the asynchronous forms for the rest of the lifecycle. Pick the payload overload first, then decide whether the caller is allowed to block at all.

Leaving a using block closes with 1001, so any other code needs an explicit Close

Close is overloaded five ways: WebSocket.Close (), WebSocket.Close (ushort), WebSocket.Close (WebSocketSharp.CloseStatusCode), WebSocket.Close (ushort, string), and WebSocket.Close (WebSocketSharp.CloseStatusCode, string). The call site is one line.

csharp
ws.Close (code, reason);

The implicit route differs from all of them. When the object sits in a using block, control leaving the block closes the connection with status code 1001, going away.

csharp
using (var ws = new WebSocket ("ws://example.com")) {
  ...
}

If the peer needs to read why a socket went down, keep the instance alive and call Close yourself before disposing. That detail decides what OnClose reports on the other machine.

Four events carry the connection, and none of them reopens it

The client surface is four events. OnOpen occurs when the connection is established and passes System.EventArgs.Empty as e, so there is nothing to read from it. OnMessage passes MessageEventArgs. OnError passes a WebSocketSharp.ErrorEventArgs instance, where e.Message returns the error message as a string and e.Exception returns a System.Exception instance when the failure came from one. OnClose passes CloseEventArgs, with e.Code returning a ushort status code and e.Reason returning a string. Each attaches the same way.

csharp
ws.OnClose += (sender, e) => {
                ...
              };

What none of the four does is restore a dropped connection. The sample code holds no reconnection path after OnClose, so retry, backoff, and session resumption are code you write yourself against these callbacks.

hybi-00 and draft75 hold older protocol drafts and are both marked no longer maintained

Three branches, and only one of them speaks the current draft. master carries production releases and targets RFC 6455. hybi-00 holds the older draft-ietf-hybi-thewebsocketprotocol-00 and is marked no longer maintained. draft75 holds the still older draft-hixie-thewebsocketprotocol-75, also marked no longer maintained. So the project's own branch layout answers the successor question: no newer protocol branch exists here, and the two alternates are reference copies rather than active work. The same dll carries both ends of the connection, so nothing in the tree splits the server into a second package. Per-message compression, secure connections, HTTP authentication, query strings, Origin headers, cookies, user headers, and connecting through an HTTP proxy server all live inside that one MIT assembly.

Editorial conclusion

Take websocket-sharp when both ends of the connection are .NET and you can live with the install. Check first that your runtime is covered by .NET Framework 3.5 or later, then pin the exact prerelease package version you tested, because the repository publishes no GitHub releases and its last push was on 2026-10-11. Skip it if you need a stable tagged channel or a scripted command line build, since the README's build and install sections offer neither.

Frequently asked questions

How can I implement WebSockets in C# with websocket-sharp?

Add the WebSocketSharp namespace, create a WebSocket with the URL, attach OnMessage, then call Connect (); Send (string), Send (byte[]), Send (System.IO.FileInfo), and Send (System.IO.Stream, int) cover the payload side, and the MIT assembly implements RFC 6455 with both client and server.

What is replacing WebSockets?

Nothing in this repository names a successor. The only alternates listed are the older hybi-00 branch for draft-ietf-hybi-thewebsocketprotocol-00 and the draft75 branch for draft-hixie-thewebsocketprotocol-75, and both are marked no longer maintained.

How to activate WebSocket in websocket-sharp?

The client walkthrough activates a socket in three moves: construct WebSocket ("ws://example.com"), attach the events you need such as OnOpen and OnMessage, then call ws.Connect (); ConnectAsync () is the asynchronous form.

Can MQTT be used over WebSockets with websocket-sharp?

The README says nothing about MQTT. What websocket-sharp supplies is the RFC 6455 transport, a client and a server in one assembly, so whether MQTT rides on top of it depends on the broker you point the client at.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. sta/websocket-sharp on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sta-websocket-sharp.svg)](https://hysenlabs.com/projects/sta-websocket-sharp)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/sta-websocket-sharp.svg)](https://hysenlabs.com/projects/sta-websocket-sharp)

Was this useful?