2014-02-11 13:40:36 +08:00

2010-10-19 10:27:39 +08:00
2013-12-03 13:24:06 +08:00
## Welcome to websocket-sharp! ##
2014-02-26 16:02:26 +08:00
**websocket-sharp** supports:
2013-11-30 00:41:30 +08:00
2013-11-30 00:57:02 +08:00
- **[RFC 6455](#supported-websocket-specifications)**
2014-07-12 15:33:38 +08:00
- **[WebSocket Client](#websocket-client)** and ** [Server ](#websocket-server )**
2013-11-30 00:57:02 +08:00
- **[Per-message Compression](#per-message-compression)** extension
2013-11-30 00:41:30 +08:00
- **[Secure Connection](#secure-connection)**
2014-01-18 16:05:57 +08:00
- **[HTTP Authentication](#http-authentication)**
2014-06-06 14:20:23 +08:00
- **[Query String, Origin header and Cookies](#query-string-origin-header-and-cookies)**
2014-08-02 10:33:39 +08:00
- **[Connecting through the HTTP Proxy server](#connecting-through-the-http-proxy-server)**
2016-07-15 14:19:08 +08:00
- .NET Framework **3.5** or later (includes compatible environment such as ** [Mono]**)
2010-10-19 10:27:39 +08:00
2013-11-22 15:15:44 +08:00
## Branches ##
2013-11-30 00:41:30 +08:00
- **[master]** for production releases.
- **[hybi-00]** for older [draft-ietf-hybi-thewebsocketprotocol-00]. No longer maintained.
- **[draft75]** for even more old [draft-hixie-thewebsocketprotocol-75]. No longer maintained.
2013-11-22 15:15:44 +08:00
2013-11-17 16:03:52 +08:00
## Build ##
2014-01-19 17:06:35 +08:00
websocket-sharp is built as a single assembly, **websocket-sharp.dll** .
2013-11-17 16:03:52 +08:00
2016-07-17 14:40:21 +08:00
websocket-sharp is developed with ** [MonoDevelop]**. So a simple way to build is to open **websocket-sharp.sln** and run build for **websocket-sharp project** with any of the build configurations (e.g. `Debug` ) in MonoDevelop.
2013-11-17 16:03:52 +08:00
2013-11-17 17:10:21 +08:00
## Install ##
### Self Build ###
2014-11-10 14:31:27 +08:00
You should add your **websocket-sharp.dll** (e.g. `/path/to/websocket-sharp/bin/Debug/websocket-sharp.dll` ) to the library references of your project.
2013-11-17 17:10:21 +08:00
2014-11-10 14:31:27 +08:00
If you would like to use that dll in your ** [Unity]** project, you should add it to any folder of your project (e.g. `Assets/Plugins` ) in **Unity Editor** .
2013-11-18 03:59:29 +08:00
2013-11-17 17:10:21 +08:00
### NuGet Gallery ###
2014-01-19 17:06:35 +08:00
websocket-sharp is available on the ** [NuGet Gallery]**, as still a **prerelease** version.
2013-11-17 17:10:21 +08:00
- **[NuGet Gallery: websocket-sharp]**
2014-11-13 13:30:27 +08:00
You can add websocket-sharp to your project with the **NuGet Package Manager** , by using the following command in the **Package Manager Console** .
2013-11-17 17:10:21 +08:00
2013-11-22 20:11:19 +08:00
PM> Install-Package WebSocketSharp -Pre
2013-11-17 17:10:21 +08:00
### Unity Asset Store ###
2014-01-19 17:06:35 +08:00
websocket-sharp is available on the **Unity Asset Store** .
2013-11-17 17:10:21 +08:00
2014-01-19 17:06:35 +08:00
- **[WebSocket-Sharp for Unity]**
2013-11-17 17:10:21 +08:00
2014-06-04 10:27:11 +08:00
It works with **Unity Free** , but there are some limitations:
2015-07-31 15:40:51 +08:00
- **[Security Sandbox of the Webplayer]** (The server isn't available in Web Player)
- **[WebGL Networking]** (Not available in WebGL)
2016-07-14 15:48:18 +08:00
- **Incompatible platform** (Not available for such UWP)
- **Limited support for the System.IO.Compression** (The compression extension isn't available on Windows)
2015-07-31 15:40:51 +08:00
- **.NET Socket Support for iOS/Android** (It requires iOS/Android Pro if your Unity is earlier than Unity 5)
2014-06-04 11:34:26 +08:00
- **.NET API 2.0 compatibility level for iOS/Android**
2016-07-14 15:48:18 +08:00
**.NET API 2.0 compatibility level for iOS/Android** may require to fix lack of some features for later than .NET 2.0, such as the `System.Func<...>` delegates (so i have added them in that asset package).
2014-06-04 10:27:11 +08:00
And it's priced at **US$15** . I think your $15 makes this project more better and accelerated, **Thank you!**
2013-11-17 17:10:21 +08:00
2010-10-19 10:27:39 +08:00
## Usage ##
2013-07-01 11:18:26 +08:00
### WebSocket Client ###
2012-08-04 14:51:31 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2013-04-12 23:41:04 +08:00
using System;
using WebSocketSharp;
2013-07-30 15:32:21 +08:00
namespace Example
{
public class Program
{
2014-07-11 14:05:44 +08:00
public static void Main (string[] args)
2013-04-12 23:41:04 +08:00
{
2014-01-01 21:09:41 +08:00
using (var ws = new WebSocket ("ws://dragonsnest.far/Laputa")) {
2014-01-25 16:35:47 +08:00
ws.OnMessage += (sender, e) =>
2016-07-04 15:29:39 +08:00
Console.WriteLine ("Laputa says: " + e.Data);
2013-04-12 23:41:04 +08:00
2013-07-30 15:32:21 +08:00
ws.Connect ();
ws.Send ("BALUS");
Console.ReadKey (true);
2013-04-12 23:41:04 +08:00
}
}
}
}
```
2012-08-04 14:51:31 +08:00
#### Step 1 ####
2010-10-19 10:27:39 +08:00
2013-01-28 15:22:24 +08:00
Required namespace.
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2012-08-08 10:32:19 +08:00
using WebSocketSharp;
```
2012-07-31 09:36:52 +08:00
2013-01-15 14:29:05 +08:00
The `WebSocket` class exists in the `WebSocketSharp` namespace.
2012-07-31 09:36:52 +08:00
2012-08-04 14:51:31 +08:00
#### Step 2 ####
2012-07-31 09:36:52 +08:00
2014-11-11 09:44:37 +08:00
Creating a new instance of the `WebSocket` class with the WebSocket URL to connect.
2012-07-31 09:36:52 +08:00
2016-09-08 15:25:42 +08:00
```csharp
var ws = new WebSocket ("ws://example.com");
```
The `WebSocket` class inherits the `System.IDisposable` interface, so you can create it with the `using` statement.
2014-11-11 09:44:37 +08:00
```csharp
2014-01-01 21:09:41 +08:00
using (var ws = new WebSocket ("ws://example.com")) {
2012-08-08 10:32:19 +08:00
...
}
```
2012-07-31 09:36:52 +08:00
2016-09-08 15:25:42 +08:00
This will **close** the WebSocket connection with status code `1001` (going away) when the control leaves the `using` block.
2012-07-31 09:36:52 +08:00
2012-08-04 14:51:31 +08:00
#### Step 3 ####
2012-07-31 09:36:52 +08:00
2012-10-12 13:53:29 +08:00
Setting the `WebSocket` events.
2012-07-31 09:36:52 +08:00
2013-07-24 22:05:33 +08:00
##### WebSocket.OnOpen Event #####
2012-07-31 09:36:52 +08:00
2013-07-15 19:42:55 +08:00
A `WebSocket.OnOpen` event occurs when the WebSocket connection has been established.
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-01 21:09:41 +08:00
ws.OnOpen += (sender, e) => {
2016-07-04 15:34:26 +08:00
...
};
2012-08-08 10:32:19 +08:00
```
2012-07-31 09:36:52 +08:00
2014-11-13 13:30:27 +08:00
`e` has passed as the `System.EventArgs.Empty` , so you don't need to use it.
2012-07-31 09:36:52 +08:00
2013-07-24 22:05:33 +08:00
##### WebSocket.OnMessage Event #####
2012-07-31 09:36:52 +08:00
2014-02-26 16:02:26 +08:00
A `WebSocket.OnMessage` event occurs when the `WebSocket` receives a message.
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-01 21:09:41 +08:00
ws.OnMessage += (sender, e) => {
2016-07-05 13:00:37 +08:00
...
};
2012-08-08 10:32:19 +08:00
```
2012-07-31 09:36:52 +08:00
2014-01-20 16:04:20 +08:00
`e` has passed as a `WebSocketSharp.MessageEventArgs` .
2013-07-19 16:29:58 +08:00
2015-12-01 15:02:20 +08:00
If you would like to get the message data, you should access `e.Data` or `e.RawData` property.
And you can determine which property you should access by checking `e.IsText` or `e.IsBinary` property.
2013-07-19 16:29:58 +08:00
2015-11-25 16:20:40 +08:00
If `e.IsText` is `true` , you should access `e.Data` that returns a `string` (represents a **text** message).
2014-01-20 16:04:20 +08:00
2015-11-25 16:20:40 +08:00
Or if `e.IsBinary` is `true` , you should access `e.RawData` that returns a `byte[]` (represents a **binary** message).
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2015-11-25 16:20:40 +08:00
if (e.IsText) {
2014-10-07 11:11:31 +08:00
// Do something with e.Data.
2014-07-13 20:41:43 +08:00
...
2013-07-15 19:42:55 +08:00
return;
}
2015-11-25 16:20:40 +08:00
if (e.IsBinary) {
2014-10-07 11:11:31 +08:00
// Do something with e.RawData.
2014-07-13 20:41:43 +08:00
...
2013-07-15 19:42:55 +08:00
return;
2012-08-08 10:36:17 +08:00
}
2012-08-08 10:32:19 +08:00
```
2012-07-31 09:36:52 +08:00
2015-11-24 15:19:31 +08:00
And if you would like to notify that a **ping** has been received, via this event, you should set the `WebSocket.EmitOnPing` property to `true` , such as the following.
2015-07-29 16:16:40 +08:00
```csharp
ws.EmitOnPing = true;
ws.OnMessage += (sender, e) => {
2016-07-05 13:00:37 +08:00
if (e.IsPing) {
// Do something to notify that a ping has been received.
...
2015-07-29 16:16:40 +08:00
2016-07-05 13:00:37 +08:00
return;
}
};
2015-07-29 16:16:40 +08:00
```
2013-07-24 22:05:33 +08:00
##### WebSocket.OnError Event #####
2012-07-31 09:36:52 +08:00
2016-09-27 14:26:01 +08:00
This event occurs when the `WebSocket` gets an error.
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-01 21:09:41 +08:00
ws.OnError += (sender, e) => {
2016-07-05 13:03:34 +08:00
...
};
2012-08-08 10:32:19 +08:00
```
2013-11-22 20:11:19 +08:00
2016-09-27 14:26:01 +08:00
`e` is passed as a `WebSocketSharp.ErrorEventArgs` instance.
If you would like to get the error message, you should access `e.Message` property.
2014-01-20 16:04:20 +08:00
2014-11-27 13:36:42 +08:00
`e.Message` property returns a `string` that represents the error message.
2012-07-31 09:36:52 +08:00
2016-09-27 14:26:01 +08:00
And `e.Exception` property returns a `System.Exception` instance that represents the cause of the error if it is due to an exception.
2014-08-25 13:45:00 +08:00
2013-07-24 22:05:33 +08:00
##### WebSocket.OnClose Event #####
2012-07-31 09:36:52 +08:00
2016-09-26 16:25:43 +08:00
This event occurs when the WebSocket connection has been closed.
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-01 21:09:41 +08:00
ws.OnClose += (sender, e) => {
2016-07-05 13:25:41 +08:00
...
};
2012-08-08 10:32:19 +08:00
```
2012-07-31 09:36:52 +08:00
2016-09-26 16:25:43 +08:00
`e` is passed as a `WebSocketSharp.CloseEventArgs` instance.
2014-01-20 16:04:20 +08:00
2016-09-26 16:25:43 +08:00
If you would like to get the reason for the close, you should access `e.Code` or `e.Reason` property.
`e.Code` property returns a `ushort` that represents the status code for the close.
`e.Reason` property returns a `string` that represents the reason for the close.
2012-07-31 09:36:52 +08:00
2012-08-04 14:51:31 +08:00
#### Step 4 ####
2012-07-31 09:36:52 +08:00
2012-10-12 13:53:29 +08:00
Connecting to the WebSocket server.
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2013-07-30 15:32:21 +08:00
ws.Connect ();
2012-08-08 10:32:19 +08:00
```
2012-07-31 09:36:52 +08:00
2014-01-27 16:05:28 +08:00
If you would like to connect to the server asynchronously, you should use the `WebSocket.ConnectAsync ()` method.
2014-01-17 19:42:43 +08:00
2012-08-04 14:51:31 +08:00
#### Step 5 ####
2012-07-31 09:36:52 +08:00
2015-05-05 14:48:07 +08:00
Sending data to the WebSocket server.
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2013-07-30 15:32:21 +08:00
ws.Send (data);
2012-08-08 10:32:19 +08:00
```
2012-07-31 09:36:52 +08:00
2014-01-21 13:51:55 +08:00
The `WebSocket.Send` method is overloaded.
2012-07-31 09:36:52 +08:00
2015-05-05 14:48:07 +08:00
You can use the `WebSocket.Send (string)` , `WebSocket.Send (byte[])` , or `WebSocket.Send (System.IO.FileInfo)` method to send the data.
2013-10-15 23:18:05 +08:00
2015-05-05 14:48:07 +08:00
If you would like to send the data asynchronously, you should use the `WebSocket.SendAsync` method.
2014-01-21 14:20:06 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-21 14:20:06 +08:00
ws.SendAsync (data, completed);
```
2013-10-15 23:18:05 +08:00
2014-07-13 20:41:43 +08:00
And also if you would like to do something when the send is complete, you should set `completed` to any `Action<bool>` delegate.
2012-07-31 09:36:52 +08:00
2012-08-04 14:51:31 +08:00
#### Step 6 ####
2012-07-31 09:36:52 +08:00
2012-10-12 13:53:29 +08:00
Closing the WebSocket connection.
2012-07-31 09:36:52 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-21 14:01:50 +08:00
ws.Close (code, reason);
2012-08-08 10:32:19 +08:00
```
2012-07-31 09:36:52 +08:00
2014-01-27 16:05:28 +08:00
If you would like to close the connection explicitly, you should use the `WebSocket.Close` method.
2012-07-31 09:36:52 +08:00
2013-11-22 20:11:19 +08:00
The `WebSocket.Close` method is overloaded.
2013-10-15 23:18:05 +08:00
2014-01-21 14:06:25 +08:00
You can use the `WebSocket.Close ()` , `WebSocket.Close (ushort)` , `WebSocket.Close (WebSocketSharp.CloseStatusCode)` , `WebSocket.Close (ushort, string)` , or `WebSocket.Close (WebSocketSharp.CloseStatusCode, string)` method to close the connection.
2012-10-16 19:31:50 +08:00
2014-01-27 16:05:28 +08:00
If you would like to close the connection asynchronously, you should use the `WebSocket.CloseAsync` method.
2014-01-17 19:42:43 +08:00
2013-07-01 11:18:26 +08:00
### WebSocket Server ###
2012-08-04 14:51:31 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2013-04-12 23:41:04 +08:00
using System;
using WebSocketSharp;
using WebSocketSharp.Server;
2013-07-30 15:32:21 +08:00
namespace Example
{
2014-09-06 16:50:10 +08:00
public class Laputa : WebSocketBehavior
2013-04-12 23:41:04 +08:00
{
2013-07-30 15:32:21 +08:00
protected override void OnMessage (MessageEventArgs e)
2013-04-12 23:41:04 +08:00
{
2013-11-18 02:17:18 +08:00
var msg = e.Data == "BALUS"
2014-04-04 15:59:38 +08:00
? "I've been balused already..."
: "I'm not available now.";
2013-11-05 20:55:16 +08:00
2013-07-30 15:32:21 +08:00
Send (msg);
2013-04-12 23:41:04 +08:00
}
}
2013-07-30 15:32:21 +08:00
public class Program
{
2014-07-11 14:05:44 +08:00
public static void Main (string[] args)
2013-04-12 23:41:04 +08:00
{
2013-10-02 13:39:56 +08:00
var wssv = new WebSocketServer ("ws://dragonsnest.far");
wssv.AddWebSocketService< Laputa > ("/Laputa");
2013-07-30 15:32:21 +08:00
wssv.Start ();
Console.ReadKey (true);
wssv.Stop ();
2013-04-12 23:41:04 +08:00
}
}
}
```
2012-08-04 14:51:31 +08:00
#### Step 1 ####
2012-08-06 22:04:57 +08:00
Required namespace.
2012-08-04 14:51:31 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2012-08-08 10:32:19 +08:00
using WebSocketSharp.Server;
```
2012-08-04 14:51:31 +08:00
2014-09-06 16:50:10 +08:00
The `WebSocketBehavior` and `WebSocketServer` classes exist in the `WebSocketSharp.Server` namespace.
2012-08-04 14:51:31 +08:00
#### Step 2 ####
2014-09-06 16:50:10 +08:00
Creating the class that inherits the `WebSocketBehavior` class.
2012-08-04 14:51:31 +08:00
2014-01-27 16:05:28 +08:00
For example, if you would like to provide an echo service,
2012-08-04 14:51:31 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2012-08-08 10:20:57 +08:00
using System;
using WebSocketSharp;
using WebSocketSharp.Server;
2014-09-06 16:50:10 +08:00
public class Echo : WebSocketBehavior
2012-08-08 10:20:57 +08:00
{
2013-07-30 15:32:21 +08:00
protected override void OnMessage (MessageEventArgs e)
2012-08-08 10:20:57 +08:00
{
2013-07-30 15:32:21 +08:00
Send (e.Data);
2012-08-08 10:20:57 +08:00
}
}
```
2012-08-04 14:51:31 +08:00
2014-01-27 16:05:28 +08:00
And if you would like to provide a chat service,
2012-08-04 14:51:31 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2012-08-08 10:32:19 +08:00
using System;
using WebSocketSharp;
using WebSocketSharp.Server;
2014-09-06 16:50:10 +08:00
public class Chat : WebSocketBehavior
2012-08-08 10:32:19 +08:00
{
2013-10-02 13:39:56 +08:00
private string _suffix;
public Chat ()
2013-12-03 14:45:14 +08:00
: this (null)
2013-10-02 13:39:56 +08:00
{
}
public Chat (string suffix)
{
2013-12-03 14:45:14 +08:00
_suffix = suffix ?? String.Empty;
2013-10-02 13:39:56 +08:00
}
2013-07-30 15:32:21 +08:00
protected override void OnMessage (MessageEventArgs e)
2012-08-08 10:32:19 +08:00
{
2013-10-02 13:39:56 +08:00
Sessions.Broadcast (e.Data + _suffix);
2012-08-08 10:32:19 +08:00
}
}
```
2012-08-04 14:51:31 +08:00
2014-09-06 16:50:10 +08:00
You can define the behavior of any WebSocket service by creating the class that inherits the `WebSocketBehavior` class.
2012-08-13 11:31:11 +08:00
2016-07-09 14:26:49 +08:00
If you override the `WebSocketBehavior.OnMessage (MessageEventArgs)` method, it will be called when the `WebSocket` used in a session in the service receives a message.
2012-08-13 11:31:11 +08:00
2016-07-09 14:26:49 +08:00
And if you override the `WebSocketBehavior.OnOpen ()` , `WebSocketBehavior.OnError (ErrorEventArgs)` , and `WebSocketBehavior.OnClose (CloseEventArgs)` methods, each of them will be called when each of the `WebSocket` events (`OnOpen`, `OnError` , and `OnClose` ) occurs.
2013-11-22 15:15:44 +08:00
2016-07-09 14:26:49 +08:00
The `WebSocketBehavior.Send` method can send data to the client on a session in the service.
2013-11-22 15:15:44 +08:00
2015-11-26 14:59:48 +08:00
If you would like to get the sessions in the service, you should access the `WebSocketBehavior.Sessions` property (returns a `WebSocketSharp.Server.WebSocketSessionManager` ).
2014-09-06 16:50:10 +08:00
2016-07-09 14:26:49 +08:00
The `WebSocketBehavior.Sessions.Broadcast` method can send data to every client in the service.
2013-11-22 15:15:44 +08:00
2012-08-06 13:34:39 +08:00
#### Step 3 ####
2012-08-04 14:51:31 +08:00
2014-11-13 13:30:27 +08:00
Creating a new instance of the `WebSocketServer` class.
2012-09-24 14:01:25 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2013-07-30 15:32:21 +08:00
var wssv = new WebSocketServer (4649);
wssv.AddWebSocketService< Echo > ("/Echo");
2013-10-02 14:45:24 +08:00
wssv.AddWebSocketService< Chat > ("/Chat");
2014-07-11 14:59:33 +08:00
wssv.AddWebSocketService< Chat > ("/ChatWithNyan", () => new Chat (" Nyan!"));
2012-09-24 14:01:25 +08:00
```
2014-11-13 13:30:27 +08:00
You can add any WebSocket service to your `WebSocketServer` with the specified behavior and path to the service, by using the `WebSocketServer.AddWebSocketService<TBehaviorWithNew> (string)` or `WebSocketServer.AddWebSocketService<TBehavior> (string, Func<TBehavior>)` method.
2013-10-02 13:39:56 +08:00
2014-09-06 16:50:10 +08:00
The type of `TBehaviorWithNew` must inherit the `WebSocketBehavior` class, and must have a public parameterless constructor.
2013-10-02 13:39:56 +08:00
2014-09-06 16:50:10 +08:00
And also the type of `TBehavior` must inherit the `WebSocketBehavior` class.
2012-09-24 14:01:25 +08:00
2014-09-06 16:50:10 +08:00
So you can use the classes created in **Step 2** to add the service.
2012-08-04 14:51:31 +08:00
2014-11-13 13:30:27 +08:00
If you create a instance of the `WebSocketServer` class without a port number, the `WebSocketServer` class set the port number to **80** automatically. So it's necessary to run with root permission.
2012-08-04 14:51:31 +08:00
2012-08-06 13:34:39 +08:00
$ sudo mono example2.exe
2012-08-04 14:51:31 +08:00
2012-08-06 13:34:39 +08:00
#### Step 4 ####
2012-08-04 14:51:31 +08:00
2014-01-21 02:04:13 +08:00
Starting the WebSocket server.
2012-08-04 14:51:31 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2013-07-30 15:32:21 +08:00
wssv.Start ();
2012-08-08 10:32:19 +08:00
```
2012-08-04 14:51:31 +08:00
2013-08-29 16:01:37 +08:00
#### Step 5 ####
2012-08-04 14:51:31 +08:00
2014-01-21 02:04:13 +08:00
Stopping the WebSocket server.
2012-08-04 14:51:31 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-21 13:22:12 +08:00
wssv.Stop (code, reason);
2012-08-08 10:32:19 +08:00
```
2012-08-04 14:51:31 +08:00
2014-01-21 02:04:13 +08:00
The `WebSocketServer.Stop` method is overloaded.
2014-01-21 13:22:12 +08:00
You can use the `WebSocketServer.Stop ()` , `WebSocketServer.Stop (ushort, string)` , or `WebSocketServer.Stop (WebSocketSharp.CloseStatusCode, string)` method to stop the server.
2014-01-21 02:04:13 +08:00
2013-07-01 11:18:26 +08:00
### HTTP Server with the WebSocket ###
2012-09-10 00:36:22 +08:00
2016-07-09 14:50:49 +08:00
I have modified the `System.Net.HttpListener` , `System.Net.HttpListenerContext` , and some other classes from ** [Mono]** to create an HTTP server that allows to accept the WebSocket handshake requests.
2012-09-10 00:36:22 +08:00
2014-01-21 16:41:00 +08:00
So websocket-sharp provides the `WebSocketSharp.Server.HttpServer` class.
2014-11-13 13:30:27 +08:00
You can add any WebSocket service to your `HttpServer` with the specified behavior and path to the service, by using the `HttpServer.AddWebSocketService<TBehaviorWithNew> (string)` or `HttpServer.AddWebSocketService<TBehavior> (string, Func<TBehavior>)` method.
2012-09-10 00:36:22 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2013-07-30 15:32:21 +08:00
var httpsv = new HttpServer (4649);
2013-10-02 13:39:56 +08:00
httpsv.AddWebSocketService< Echo > ("/Echo");
2013-10-02 14:45:24 +08:00
httpsv.AddWebSocketService< Chat > ("/Chat");
2014-07-11 14:59:33 +08:00
httpsv.AddWebSocketService< Chat > ("/ChatWithNyan", () => new Chat (" Nyan!"));
2012-09-10 00:36:22 +08:00
```
2014-07-13 20:41:43 +08:00
For more information, would you see ** [Example3]**?
2013-07-01 11:18:26 +08:00
2013-11-05 20:55:16 +08:00
### WebSocket Extensions ###
#### Per-message Compression ####
2015-08-02 17:18:27 +08:00
websocket-sharp supports the ** [Per-message Compression][compression]** extension (but doesn't support this extension with the [context take over]).
2013-11-05 20:55:16 +08:00
2015-08-02 17:18:27 +08:00
As a WebSocket client, if you would like to enable this extension, you should set such as the following.
2013-11-05 20:55:16 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-03-04 16:02:41 +08:00
ws.Compression = CompressionMethod.Deflate;
2013-11-05 20:55:16 +08:00
```
2016-07-08 13:49:19 +08:00
And then your client will send the following header in the handshake request to the server.
2013-11-05 20:55:16 +08:00
2015-03-25 16:43:27 +08:00
Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover
2013-11-05 20:55:16 +08:00
2015-03-26 16:02:20 +08:00
If the server accepts this extension, it will return the same header which has the corresponding value. And when your client receives it, this extension will be available.
2013-11-05 20:55:16 +08:00
2015-08-02 17:18:27 +08:00
#### Ignoring the extensions ####
2015-07-30 16:18:04 +08:00
As a WebSocket server, if you would like to ignore the extensions requested from a client, you should set the `WebSocketBehavior.IgnoreExtensions` property to `true` in your `WebSocketBehavior` constructor or initializing it, such as the following.
```csharp
wssv.AddWebSocketService< Chat > (
"/Chat",
2016-01-26 15:48:07 +08:00
() =>
new Chat () {
// To ignore the extensions requested from a client.
IgnoreExtensions = true
}
);
2015-07-30 16:18:04 +08:00
```
2016-07-12 13:46:06 +08:00
If it's set to `true` , the service will not return the **Sec-WebSocket-Extensions** header in its handshake response.
2015-07-30 16:18:04 +08:00
2015-08-02 17:18:27 +08:00
I think this is useful when you get something error in connecting the server and exclude the extensions as a cause of the error.
2015-07-30 16:18:04 +08:00
2013-07-19 16:29:58 +08:00
### Secure Connection ###
2014-11-09 12:55:36 +08:00
websocket-sharp supports the **Secure Connection** with **SSL/TLS** .
2014-01-21 19:50:14 +08:00
2016-08-05 14:23:30 +08:00
As a **WebSocket Client** , you should create a new instance of the `WebSocket` class with a **wss** scheme WebSocket URL.
2013-07-19 16:29:58 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-01 21:09:41 +08:00
using (var ws = new WebSocket ("wss://example.com")) {
2013-07-19 16:29:58 +08:00
...
}
```
2014-11-05 10:21:10 +08:00
And if you would like to use the custom validation for the server certificate, you should set the `WebSocket.SslConfiguration.ServerCertificateValidationCallback` property.
2013-07-19 16:29:58 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-11-09 12:55:36 +08:00
ws.SslConfiguration.ServerCertificateValidationCallback =
(sender, certificate, chain, sslPolicyErrors) => {
// Do something to validate the server certificate.
...
2014-07-13 20:41:43 +08:00
2014-11-09 12:55:36 +08:00
return true; // If the server certificate is valid.
};
2013-07-19 16:29:58 +08:00
```
2014-09-06 16:50:10 +08:00
If you set this property to nothing, the validation does nothing with the server certificate, and returns `true` .
2013-07-19 16:29:58 +08:00
2014-11-13 13:30:27 +08:00
As a **WebSocket Server** , you should create a new instance of the `WebSocketServer` or `HttpServer` class with some settings for secure connection, such as the following.
2013-07-19 16:29:58 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2015-05-05 14:48:07 +08:00
var wssv = new WebSocketServer (5963, true);
2014-11-09 12:55:36 +08:00
wssv.SslConfiguration.ServerCertificate =
new X509Certificate2 ("/path/to/cert.pfx", "password for cert.pfx");
2013-07-19 16:29:58 +08:00
```
2014-01-18 16:05:57 +08:00
### HTTP Authentication ###
2014-01-22 16:49:38 +08:00
websocket-sharp supports the ** [HTTP Authentication (Basic/Digest)][rfc2617]**.
2014-01-18 16:05:57 +08:00
2014-11-13 13:30:27 +08:00
As a **WebSocket Client** , you should set a pair of user name and password for the HTTP authentication, by using the `WebSocket.SetCredentials (string, string, bool)` method before connecting.
2014-01-18 16:05:57 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-07-13 20:41:43 +08:00
ws.SetCredentials ("nobita", "password", preAuth);
2014-01-18 16:05:57 +08:00
```
2016-08-15 16:15:17 +08:00
If `preAuth` is `true` , the `WebSocket` will send the credentials for the Basic authentication with the first handshake request to the server.
2014-01-18 16:05:57 +08:00
2016-08-15 16:15:17 +08:00
Otherwise, the `WebSocket` will send the credentials for either the Basic or Digest (determined by the unauthorized response to the first handshake request) authentication with the second handshake request to the server.
2014-01-18 16:05:57 +08:00
2014-11-10 14:31:27 +08:00
As a **WebSocket Server** , you should set an HTTP authentication scheme, a realm, and any function to find the user credentials before starting, such as the following.
2014-01-18 16:05:57 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-18 16:05:57 +08:00
wssv.AuthenticationSchemes = AuthenticationSchemes.Basic;
wssv.Realm = "WebSocket Test";
2014-07-11 14:05:44 +08:00
wssv.UserCredentialsFinder = id => {
2016-07-06 14:14:25 +08:00
var name = id.Name;
2014-11-10 14:31:27 +08:00
2016-07-06 14:14:25 +08:00
// Return user name, password, and roles.
return name == "nobita"
? new NetworkCredential (name, "password", "gunfighter")
: null; // If the user credentials aren't found.
};
2014-01-18 16:05:57 +08:00
```
2014-11-10 14:31:27 +08:00
If you would like to provide the Digest authentication, you should set such as the following.
2014-01-18 16:05:57 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-01-18 16:05:57 +08:00
wssv.AuthenticationSchemes = AuthenticationSchemes.Digest;
```
2014-06-05 11:27:50 +08:00
### Query String, Origin header and Cookies ###
2014-06-05 11:07:33 +08:00
2016-07-08 13:55:23 +08:00
As a **WebSocket Client** , if you would like to send the **Query String** with the handshake request to the server, you should create a new instance of the `WebSocket` class with the WebSocket URL that includes the [Query] string parameters.
2014-06-05 11:07:33 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-06-05 11:07:33 +08:00
using (var ws = new WebSocket ("ws://example.com/?name=nobita")) {
...
}
```
2016-07-08 13:55:23 +08:00
And if you would like to send the **Origin** header with the handshake request to the server, you should set the `WebSocket.Origin` property to an allowable value as the [Origin] header before connecting, such as the following.
2014-06-05 11:27:50 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-06-05 11:27:50 +08:00
ws.Origin = "http://example.com";
```
2016-07-08 13:55:23 +08:00
And also if you would like to send the **Cookies** with the handshake request to the server, you should set any cookie by using the `WebSocket.SetCookie (WebSocketSharp.Net.Cookie)` method before connecting, such as the following.
2014-06-05 11:27:50 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-06-05 11:27:50 +08:00
ws.SetCookie (new Cookie ("name", "nobita"));
```
2016-07-08 13:55:23 +08:00
As a **WebSocket Server** , if you would like to get the **Query String** included in a handshake request, you should access the `WebSocketBehavior.Context.QueryString` property, such as the following.
2014-06-05 11:07:33 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-09-06 16:50:10 +08:00
public class Chat : WebSocketBehavior
2014-06-05 11:07:33 +08:00
{
private string _name;
...
protected override void OnOpen ()
{
2014-07-11 14:05:44 +08:00
_name = Context.QueryString["name"];
2014-06-05 11:07:33 +08:00
}
...
}
```
2016-07-08 13:55:23 +08:00
And if you would like to validate the **Origin** header, **Cookies** , or both included in a handshake request, you should set each validation with your `WebSocketBehavior` , for example, by using the `AddWebSocketService<TBehavior> (string, Func<TBehavior>)` method with initializing, such as the following.
2014-03-19 02:25:07 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-03-19 02:25:07 +08:00
wssv.AddWebSocketService< Chat > (
"/Chat",
2016-07-07 14:12:43 +08:00
() =>
new Chat () {
OriginValidator = val => {
// Check the value of the Origin header, and return true if valid.
Uri origin;
return !val.IsNullOrEmpty ()
& & Uri.TryCreate (val, UriKind.Absolute, out origin)
& & origin.Host == "example.com";
},
CookiesValidator = (req, res) => {
// Check the cookies in 'req', and set the cookies to send to
// the client with 'res' if necessary.
foreach (Cookie cookie in req) {
cookie.Expired = true;
res.Add (cookie);
}
return true; // If valid.
}
2014-03-19 02:25:07 +08:00
}
2016-07-07 14:12:43 +08:00
);
2014-03-19 02:25:07 +08:00
```
2014-11-16 13:37:54 +08:00
And also if you would like to get each value of the Origin header and cookies, you should access each of the `WebSocketBehavior.Context.Origin` and `WebSocketBehavior.Context.CookieCollection` properties.
2014-06-08 15:42:26 +08:00
2014-08-02 10:33:39 +08:00
### Connecting through the HTTP Proxy server ###
2014-08-02 10:47:24 +08:00
websocket-sharp supports to connect through the **HTTP Proxy** server.
2014-08-02 10:33:39 +08:00
2016-07-18 16:13:10 +08:00
If you would like to connect to a WebSocket server through the HTTP proxy server, you should set the proxy server URL, and if necessary, a pair of user name and password for the proxy server authentication (Basic/Digest), by using the `WebSocket.SetProxy (string, string, string)` method before connecting.
2014-08-02 10:33:39 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-08-02 10:33:39 +08:00
var ws = new WebSocket ("ws://example.com");
2014-08-07 18:43:14 +08:00
ws.SetProxy ("http://localhost:3128", "nobita", "password");
2014-08-02 10:33:39 +08:00
```
2016-07-18 16:13:10 +08:00
I have tested this with ** [Squid]**. It's necessary to disable the following configuration option in **squid.conf** (e.g. `/etc/squid/squid.conf` ).
2014-08-02 10:33:39 +08:00
```
# Deny CONNECT to other than SSL ports
#http_access deny CONNECT !SSL_ports
```
2013-07-15 19:42:55 +08:00
### Logging ###
2016-07-10 13:54:41 +08:00
The `WebSocket` class has the own logging function.
2013-07-15 19:42:55 +08:00
2014-11-10 14:31:27 +08:00
You can use it with the `WebSocket.Log` property (returns a `WebSocketSharp.Logger` ).
2013-07-15 19:42:55 +08:00
2014-03-02 21:15:41 +08:00
So if you would like to change the current logging level (`WebSocketSharp.LogLevel.Error` as the default), you should set the `WebSocket.Log.Level` property to any of the `LogLevel` enum values.
2013-07-15 19:42:55 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2014-03-02 21:15:41 +08:00
ws.Log.Level = LogLevel.Debug;
2013-07-15 19:42:55 +08:00
```
2014-07-13 20:41:43 +08:00
The above means a log with lower than `LogLevel.Debug` cannot be outputted.
2013-07-15 19:42:55 +08:00
2014-03-02 21:15:41 +08:00
And if you would like to output a log, you should use any of the output methods. The following outputs a log with `LogLevel.Debug` .
2013-07-15 19:42:55 +08:00
2014-11-12 10:20:37 +08:00
```csharp
2013-07-30 15:32:21 +08:00
ws.Log.Debug ("This is a debug message.");
2013-07-15 19:42:55 +08:00
```
2016-07-10 13:54:41 +08:00
The `WebSocketServer` and `HttpServer` classes have the same logging function.
2013-07-15 19:42:55 +08:00
2012-07-31 09:36:52 +08:00
## Examples ##
2014-07-12 15:33:38 +08:00
Examples using websocket-sharp.
2012-07-31 09:36:52 +08:00
### Example ###
2014-01-22 13:34:00 +08:00
**[Example]** connects to the ** [Echo server]** with the WebSocket.
2012-07-31 09:36:52 +08:00
2012-08-04 14:51:31 +08:00
### Example2 ###
2014-01-22 13:34:00 +08:00
**[Example2]** starts a WebSocket server.
2012-09-10 00:36:22 +08:00
### Example3 ###
2016-07-08 13:49:19 +08:00
**[Example3]** starts an HTTP server that allows to accept the WebSocket handshake requests.
2012-08-04 14:51:31 +08:00
2015-12-01 15:02:20 +08:00
Would you access to [http://localhost:4649 ](http://localhost:4649 ) to do **WebSocket Echo Test** with your web browser while Example3 is running?
2012-09-24 14:01:25 +08:00
2013-05-01 13:27:24 +08:00
## Supported WebSocket Specifications ##
2012-07-31 09:36:52 +08:00
2014-03-19 02:25:07 +08:00
websocket-sharp supports ** [RFC 6455][rfc6455]**, and it's based on the following WebSocket references:
2013-10-28 15:29:51 +08:00
2013-11-19 16:15:08 +08:00
- **[The WebSocket Protocol][rfc6455]**
- **[The WebSocket API][api]**
2013-10-28 15:29:51 +08:00
- **[Compression Extensions for WebSocket][compression]**
Thanks for translating to japanese.
2013-11-19 16:15:08 +08:00
- **[The WebSocket Protocol 日本語訳][rfc6455_ja]**
- **[The WebSocket API 日本語訳][api_ja]**
2013-10-28 15:29:51 +08:00
2012-07-31 09:36:52 +08:00
## License ##
2014-01-22 13:44:42 +08:00
websocket-sharp is provided under ** [The MIT License]**.
2012-07-31 09:36:52 +08:00
[Echo server]: http://www.websocket.org/echo.html
[Example]: https://github.com/sta/websocket-sharp/tree/master/Example
2012-08-04 14:51:31 +08:00
[Example2]: https://github.com/sta/websocket-sharp/tree/master/Example2
2012-09-10 00:36:22 +08:00
[Example3]: https://github.com/sta/websocket-sharp/tree/master/Example3
2013-11-18 02:17:18 +08:00
[Mono]: http://www.mono-project.com
2013-11-17 16:03:52 +08:00
[MonoDevelop]: http://monodevelop.com
2013-11-17 17:10:21 +08:00
[NuGet Gallery]: http://www.nuget.org
[NuGet Gallery: websocket-sharp]: http://www.nuget.org/packages/WebSocketSharp
2016-01-27 15:30:48 +08:00
[Origin]: http://tools.ietf.org/html/rfc6454#section-7
2014-06-06 14:20:23 +08:00
[Query]: http://tools.ietf.org/html/rfc3986#section-3.4
2014-06-04 10:27:11 +08:00
[Security Sandbox of the Webplayer]: http://docs.unity3d.com/Manual/SecuritySandbox.html
2014-08-02 10:33:39 +08:00
[Squid]: http://www.squid-cache.org
2013-11-19 16:15:08 +08:00
[The MIT License]: https://raw.github.com/sta/websocket-sharp/master/LICENSE.txt
2013-11-18 03:59:29 +08:00
[Unity]: http://unity3d.com
2015-07-31 15:40:51 +08:00
[WebGL Networking]: http://docs.unity3d.com/Manual/webgl-networking.html
2014-01-19 17:12:38 +08:00
[WebSocket-Sharp for Unity]: http://u3d.as/content/sta-blockhead/websocket-sharp-for-unity
[api]: http://www.w3.org/TR/websockets
2013-11-19 16:15:08 +08:00
[api_ja]: http://www.hcn.zaq.ne.jp/___/WEB/WebSocket-ja.html
2015-03-25 16:43:27 +08:00
[compression]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-19
[context take over]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-19#section-8.1.1
2013-11-22 15:15:44 +08:00
[draft-hixie-thewebsocketprotocol-75]: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75
[draft-ietf-hybi-thewebsocketprotocol-00]: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
[draft75]: https://github.com/sta/websocket-sharp/tree/draft75
[hybi-00]: https://github.com/sta/websocket-sharp/tree/hybi-00
[master]: https://github.com/sta/websocket-sharp/tree/master
2014-01-22 16:49:38 +08:00
[rfc2617]: http://tools.ietf.org/html/rfc2617
2013-11-19 16:15:08 +08:00
[rfc6455]: http://tools.ietf.org/html/rfc6455
[rfc6455_ja]: http://www.hcn.zaq.ne.jp/___/WEB/RFC6455-ja.html