This repository is a maintained fork of websocket-sharp, a C# implementation of the WebSocket protocol client and server.
This fork includes improved RFC 7692 permessage-deflate compatibility, including support for valid server_max_window_bits negotiation.
websocket-sharp supports:
- RFC 6455 WebSockets
- WebSocket Client and Server
- RFC 7692 Per-message Compression
- Secure WebSocket connections (
wss://) - HTTP Authentication (Basic/Digest)
- Query strings, Origin headers, and Cookies
- HTTP proxy connections
This fork currently builds for:
- .NET Framework 3.5
- .NET Framework 4.5
- .NET Standard 2.0
The project produces a single assembly named:
websocket-sharp.dll
The original websocket-sharp implementation supports the WebSocket permessage-deflate extension, but its extension-response validation could reject otherwise valid responses when a server returned parameters such as:
server_max_window_bits=11
RFC 7692 allows server_max_window_bits values from 8 through 15.
This fork updates extension-response validation so valid values within that range are accepted while invalid or unsupported values continue to be rejected.
For example, a server may negotiate compression with a response containing:
permessage-deflate;
server_no_context_takeover;
client_no_context_takeover;
server_max_window_bits=11
This change improves interoperability with WebSocket servers that negotiate RFC 7692 compression parameters rather than returning an extension response identical to the client's request.
This change affects WebSocket compression negotiation.
It does not modify or extend TLS support on older .NET or Mono environments. TLS handshake compatibility is separate from WebSocket extension negotiation.
master- stable and release-ready codetest- development and experimental changes
To build all supported targets in Release configuration:
dotnet build .\websocket-sharp\websocket-sharp.csproj -c ReleaseBuild outputs are generated separately for:
net35
net45
netstandard2.0
This maintained fork is published as:
WebSocketSharp-NetCompression
Using the .NET CLI:
dotnet add package WebSocketSharp-NetCompressionUsing the NuGet Package Manager Console:
Install-Package WebSocketSharp-NetCompressionPrecompiled framework-specific assemblies are also available from the GitHub Releases page.
Choose the assembly appropriate for your target framework and add websocket-sharp.dll as a reference to your project.
The release archive contains builds for:
net35/
net45/
netstandard2.0/
If you use the DLL in a Unity project, add the appropriate websocket-sharp.dll to a suitable location such as Assets/Plugins.
using System;
using WebSocketSharp;
namespace Example
{
public class Program
{
public static void Main (string[] args)
{
using (var ws = new WebSocket ("ws://example.com")) {
ws.OnMessage += (sender, e) =>
Console.WriteLine ("Received: " + e.Data);
ws.Connect ();
ws.Send ("Hello!");
Console.ReadKey (true);
}
}
}
}Required namespace:
using WebSocketSharp;Create a new WebSocket instance with the WebSocket URL:
var ws = new WebSocket ("ws://example.com");WebSocket implements System.IDisposable, so it can be used with a using statement:
using (var ws = new WebSocket ("ws://example.com")) {
...
}The WebSocket connection will be closed when execution leaves the using block.
Occurs when the WebSocket connection has been established.
ws.OnOpen += (sender, e) => {
...
};Occurs when a message is received.
ws.OnMessage += (sender, e) => {
...
};A WebSocketSharp.MessageEventArgs instance is passed as e.
Text messages can be accessed through:
e.DataRaw message data can be accessed through:
e.RawDataFor example:
if (e.IsText) {
// Use e.Data.
return;
}
if (e.IsBinary) {
// Use e.RawData.
return;
}To emit received ping frames through OnMessage, set:
ws.EmitOnPing = true;For example:
ws.EmitOnPing = true;
ws.OnMessage += (sender, e) => {
if (e.IsPing) {
// Handle received ping.
return;
}
};Occurs when an error is encountered.
ws.OnError += (sender, e) => {
...
};The error message is available from:
e.MessageIf the error was caused by an exception, it may be available from:
e.ExceptionOccurs when the WebSocket connection is closed.
ws.OnClose += (sender, e) => {
...
};The close status code and reason are available through:
e.Code
e.ReasonConnect synchronously with:
ws.Connect ();For asynchronous connection:
ws.ConnectAsync ();Send data with:
ws.Send (data);WebSocket.Send supports several data types, including:
ws.Send (stringData);
ws.Send (byteArray);
ws.Send (fileInfo);Asynchronous sending is also supported:
ws.SendAsync (data, completed);The completed callback can be used to determine whether the asynchronous operation succeeded.
Close explicitly with:
ws.Close ();Other overloads allow you to provide a close status code and reason.
Asynchronous closing is also available through:
ws.CloseAsync ();using System;
using WebSocketSharp;
using WebSocketSharp.Server;
namespace Example
{
public class Echo : WebSocketBehavior
{
protected override void OnMessage (MessageEventArgs e)
{
Send (e.Data);
}
}
public class Program
{
public static void Main (string[] args)
{
var wssv = new WebSocketServer (4649);
wssv.AddWebSocketService<Echo> ("/Echo");
wssv.Start ();
Console.ReadKey (true);
wssv.Stop ();
}
}
}Required namespace:
using WebSocketSharp.Server;WebSocket services are created by deriving from:
WebSocketBehaviorFor example:
public class Echo : WebSocketBehavior
{
protected override void OnMessage (MessageEventArgs e)
{
Send (e.Data);
}
}A service can be registered with:
var wssv = new WebSocketServer (4649);
wssv.AddWebSocketService<Echo> ("/Echo");Start the server with:
wssv.Start ();Stop it with:
wssv.Stop ();WebSocketBehavior can also override events including:
OnOpen ()
OnMessage (MessageEventArgs)
OnError (ErrorEventArgs)
OnClose (CloseEventArgs)A WebSocketBehavior can access its session manager through:
SessionsMessages can be broadcast to connected sessions with:
Sessions.Broadcast (data);websocket-sharp also provides:
WebSocketSharp.Server.HttpServerWebSocket services can be added to an HTTP server in the same general manner as a WebSocketServer.
For example:
var httpsv = new HttpServer (4649);
httpsv.AddWebSocketService<Echo> ("/Echo");
httpsv.Start ();websocket-sharp supports the RFC 7692 permessage-deflate extension without context takeover.
To enable compression as a WebSocket client, set the WebSocket.Compression property before connecting:
ws.Compression = CompressionMethod.Deflate;The client sends a WebSocket extension request similar to:
Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover
A compatible server may return a negotiated extension response containing additional valid parameters.
For example:
Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover; server_max_window_bits=11
This fork accepts valid server_max_window_bits values from 8 through 15, in accordance with RFC 7692.
The extension becomes active when compatible compression parameters are successfully negotiated during the WebSocket handshake.
A WebSocket server can ignore extension requests by setting:
IgnoreExtensions = trueFor example:
wssv.AddWebSocketService<Chat> (
"/Chat",
() =>
new Chat () {
IgnoreExtensions = true
}
);If enabled, the service will not return a Sec-WebSocket-Extensions header in its handshake response.
websocket-sharp supports SSL/TLS WebSocket connections.
As a client, use a wss:// URL:
var ws = new WebSocket ("wss://example.com");A custom server certificate validation callback can be configured through:
ws.SslConfiguration.ServerCertificateValidationCallback =
(sender, certificate, chain, sslPolicyErrors) => {
// Validate the certificate.
return true;
};A secure WebSocket server can be configured with a certificate:
var wssv = new WebSocketServer (5963, true);
wssv.SslConfiguration.ServerCertificate =
new X509Certificate2 ("/path/to/cert.pfx", "password");TLS capabilities ultimately depend on the .NET or Mono runtime on which websocket-sharp is running.
websocket-sharp supports Basic and Digest HTTP authentication.
As a client:
ws.SetCredentials ("username", "password", preAuth);If preAuth is true, credentials for Basic authentication are sent with the initial request.
A server can configure an authentication scheme and credential lookup.
For example:
wssv.AuthenticationSchemes = AuthenticationSchemes.Basic;
wssv.Realm = "WebSocket Test";
wssv.UserCredentialsFinder = id => {
var name = id.Name;
return name == "user"
? new NetworkCredential (name, "password", "role")
: null;
};Digest authentication can be selected with:
wssv.AuthenticationSchemes = AuthenticationSchemes.Digest;Include query parameters in the WebSocket URL:
var ws = new WebSocket ("ws://example.com/?name=user");On the server, query parameters are available through:
Context.QueryStringA client can set the Origin header before connecting:
ws.Origin = "http://example.com";On the server, the Origin is available through:
Context.OriginA client can add cookies using:
ws.SetCookie (new Cookie ("name", "value"));Server-side cookies are available through:
Context.CookieCollectionCustom Origin and cookie validation can also be configured on a WebSocketBehavior.
A client can connect through an HTTP proxy using:
var ws = new WebSocket ("ws://example.com");
ws.SetProxy (
"http://localhost:3128",
"username",
"password"
);Proxy authentication supports Basic/Digest authentication.
WebSocket includes a logging system available through:
ws.LogThe logging level can be changed with:
ws.Log.Level = LogLevel.Debug;Messages can be written through methods such as:
ws.Log.Debug ("This is a debug message.");WebSocketServer and HttpServer provide similar logging functionality.
The repository contains example projects demonstrating websocket-sharp usage.
websocket-sharp is primarily based on:
This repository is a maintained fork of the original websocket-sharp project.
Original websocket-sharp was created by sta.blockhead.
This fork includes additional maintenance and RFC 7692 compatibility changes by TylerJG92.
The original copyright notice has been retained.
websocket-sharp is provided under the MIT License.
Copyright (c) 2010-2017 sta.blockhead
Copyright (c) 2026 TylerJG92
