websocket-sharp使用手冊

Welcome to websocket-sharp!

websocket-sharp supports:

Build

websocket-sharp is built as a single assembly, websocket-sharp.dll.

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.

Install

Self Build

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.

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.

NuGet Gallery

websocket-sharp is available on the NuGet Gallery, as still a prerelease version.

You can add websocket-sharp to your project with the NuGet Package Manager, by using the following command in the Package Manager Console.

PM> Install-Package WebSocketSharp -Pre

Unity Asset Store

websocket-sharp is available on the Unity Asset Store.

It works with Unity Free, but there are some limitations:

  • Security Sandbox of the Webplayer (The server isn't available in Web Player)
  • WebGL Networking (Not available in WebGL)
  • Incompatible platform (Not available for such UWP)
  • Limited support for the System.IO.Compression (The compression extension isn't available on Windows)
  • .NET Socket Support for iOS/Android (It requires iOS/Android Pro if your Unity is earlier than Unity 5)
  • .NET API 2.0 compatibility level for iOS/Android

.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).

And it's priced at US$15. I think your $15 makes this project more better and accelerated, Thank you!

Usage

WebSocket Client

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);
      }
    }
  }
}

Step 1

Required namespace.

using WebSocketSharp;

The WebSocket class exists in the WebSocketSharp namespace.

Step 2

Creating a new instance of the WebSocket class with the WebSocket URL to connect.

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

The WebSocket class inherits the System.IDisposable interface, so you can use the using statement. And the WebSocket connection will be closed with close status 1001 (going away) when the control leaves the using block.

Step 3

Setting the WebSocket events.

WebSocket.OnOpen Event

A WebSocket.OnOpen event occurs when the WebSocket connection has been established.

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

e has passed as the System.EventArgs.Empty, so you don't need to use it.

WebSocket.OnMessage Event

A WebSocket.OnMessage event occurs when the WebSocket receives a message.

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

e has passed as a WebSocketSharp.MessageEventArgs.

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.

If e.IsText is true, you should access e.Data that returns a string (represents a text message).

Or if e.IsBinary is true, you should access e.RawData that returns a byte[] (represents a binary message).

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

  return;
}

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

  return;
}

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.

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

      return;
    }
  };
WebSocket.OnError Event

A WebSocket.OnError event occurs when the WebSocket gets an error.

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

e has passed as a WebSocketSharp.ErrorEventArgs.

e.Message property returns a string that represents the error message.

If the error is due to an exception, e.Exception property returns a System.Exception instance that caused the error.

WebSocket.OnClose Event

A WebSocket.OnClose event occurs when the WebSocket connection has been closed.

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

e has passed as a WebSocketSharp.CloseEventArgs.

e.Code property returns a ushort that represents the status code for the close, and e.Reason property returns a string that represents the reason for the close.

Step 4

Connecting to the WebSocket server.

ws.Connect ();

If you would like to connect to the server asynchronously, you should use the WebSocket.ConnectAsync () method.

Step 5

Sending data to the WebSocket server.

ws.Send (data);

The WebSocket.Send method is overloaded.

You can use the WebSocket.Send (string), WebSocket.Send (byte[]), or WebSocket.Send (System.IO.FileInfo) method to send the data.

If you would like to send the data asynchronously, you should use the WebSocket.SendAsync method.

ws.SendAsync (data, completed);

And also if you would like to do something when the send is complete, you should set completed to any Action<bool> delegate.

Step 6

Closing the WebSocket connection.

ws.Close (code, reason);

If you would like to close the connection explicitly, you should use the WebSocket.Close method.

The WebSocket.Close method is overloaded.

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.

If you would like to close the connection asynchronously, you should use the WebSocket.CloseAsync method.

WebSocket Server

using System;
using WebSocketSharp;
using WebSocketSharp.Server;

namespace Example
{
  public class Laputa : WebSocketBehavior
  {
    protected override void OnMessage (MessageEventArgs e)
    {
      var msg = e.Data == "BALUS"
                ? "I've been balused already..."
                : "I'm not available now.";

      Send (msg);
    }
  }

  public class Program
  {
    public static void Main (string[] args)
    {
      var wssv = new WebSocketServer ("ws://dragonsnest.far");
      wssv.AddWebSocketService<Laputa> ("/Laputa");
      wssv.Start ();
      Console.ReadKey (true);
      wssv.Stop ();
    }
  }
}

Step 1

Required namespace.

using WebSocketSharp.Server;

The WebSocketBehavior and WebSocketServer classes exist in the WebSocketSharp.Server namespace.

Step 2

Creating the class that inherits the WebSocketBehavior class.

For example, if you would like to provide an echo service,

using System;
using WebSocketSharp;
using WebSocketSharp.Server;

public class Echo : WebSocketBehavior
{
  protected override void OnMessage (MessageEventArgs e)
  {
    Send (e.Data);
  }
}

And if you would like to provide a chat service,

using System;
using WebSocketSharp;
using WebSocketSharp.Server;

public class Chat : WebSocketBehavior
{
  private string _suffix;

  public Chat ()
    : this (null)
  {
  }

  public Chat (string suffix)
  {
    _suffix = suffix ?? String.Empty;
  }

  protected override void OnMessage (MessageEventArgs e)
  {
    Sessions.Broadcast (e.Data + _suffix);
  }
}

You can define the behavior of any WebSocket service by creating the class that inherits the WebSocketBehavior class.

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.

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.

The WebSocketBehavior.Send method can send data to the client on a session in the service.

If you would like to get the sessions in the service, you should access the WebSocketBehavior.Sessions property (returns a WebSocketSharp.Server.WebSocketSessionManager).

The WebSocketBehavior.Sessions.Broadcast method can send data to every client in the service.

Step 3

Creating a new instance of the WebSocketServer class.

var wssv = new WebSocketServer (4649);
wssv.AddWebSocketService<Echo> ("/Echo");
wssv.AddWebSocketService<Chat> ("/Chat");
wssv.AddWebSocketService<Chat> ("/ChatWithNyan", () => new Chat (" Nyan!"));

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.

The type of TBehaviorWithNew must inherit the WebSocketBehavior class, and must have a public parameterless constructor.

And also the type of TBehavior must inherit the WebSocketBehavior class.

So you can use the classes created in Step 2 to add the service.

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.

$ sudo mono example2.exe

Step 4

Starting the WebSocket server.

wssv.Start ();

Step 5

Stopping the WebSocket server.

wssv.Stop (code, reason);

The WebSocketServer.Stop method is overloaded.

You can use the WebSocketServer.Stop (), WebSocketServer.Stop (ushort, string), or WebSocketServer.Stop (WebSocketSharp.CloseStatusCode, string) method to stop the server.

HTTP Server with the WebSocket

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.

So websocket-sharp provides the WebSocketSharp.Server.HttpServer class.

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.

var httpsv = new HttpServer (4649);
httpsv.AddWebSocketService<Echo> ("/Echo");
httpsv.AddWebSocketService<Chat> ("/Chat");
httpsv.AddWebSocketService<Chat> ("/ChatWithNyan", () => new Chat (" Nyan!"));

For more information, would you see Example3?

WebSocket Extensions

Per-message Compression

websocket-sharp supports the Per-message Compression extension (but doesn't support this extension with the context take over).

As a WebSocket client, if you would like to enable this extension, you should set such as the following.

ws.Compression = CompressionMethod.Deflate;

And then your client will send the following header in the handshake request to the server.

Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover

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.

Ignoring the extensions

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.

wssv.AddWebSocketService<Chat> (
  "/Chat",
  () =>
    new Chat () {
      // To ignore the extensions requested from a client.
      IgnoreExtensions = true
    }
);

If it's set to true, the service will not return the Sec-WebSocket-Extensions header in its handshake response.

I think this is useful when you get something error in connecting the server and exclude the extensions as a cause of the error.

Secure Connection

websocket-sharp supports the Secure Connection with SSL/TLS.

As a WebSocket Client, you should create a new instance of the WebSocket class with the wss scheme WebSocket URL.

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

And if you would like to use the custom validation for the server certificate, you should set the WebSocket.SslConfiguration.ServerCertificateValidationCallback property.

ws.SslConfiguration.ServerCertificateValidationCallback =
  (sender, certificate, chain, sslPolicyErrors) => {
    // Do something to validate the server certificate.
    ...

    return true; // If the server certificate is valid.
  };

If you set this property to nothing, the validation does nothing with the server certificate, and returns true.

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.

var wssv = new WebSocketServer (5963, true);
wssv.SslConfiguration.ServerCertificate =
  new X509Certificate2 ("/path/to/cert.pfx", "password for cert.pfx");

HTTP Authentication

websocket-sharp supports the HTTP Authentication (Basic/Digest).

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.

ws.SetCredentials ("nobita", "password", preAuth);

If preAuth is true, the WebSocket sends the Basic authentication credentials with the first handshake request to the server.

Or if preAuth is false, the WebSocket sends either the Basic or Digest (determined by the unauthorized response to the first handshake request) authentication credentials with the second handshake request to the server.

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.

wssv.AuthenticationSchemes = AuthenticationSchemes.Basic;
wssv.Realm = "WebSocket Test";
wssv.UserCredentialsFinder = id => {
    var name = id.Name;

    // Return user name, password, and roles.
    return name == "nobita"
           ? new NetworkCredential (name, "password", "gunfighter")
           : null; // If the user credentials aren't found.
  };

If you would like to provide the Digest authentication, you should set such as the following.

wssv.AuthenticationSchemes = AuthenticationSchemes.Digest;

Query String, Origin header and Cookies

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.

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

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.

ws.Origin = "http://example.com";

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.

ws.SetCookie (new Cookie ("name", "nobita"));

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.

public class Chat : WebSocketBehavior
{
  private string _name;
  ...

  protected override void OnOpen ()
  {
    _name = Context.QueryString["name"];
  }

  ...
}

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.

wssv.AddWebSocketService<Chat> (
  "/Chat",
  () =>
    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.
        }
    }
);

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.

Connecting through the HTTP Proxy server

websocket-sharp supports to connect through the HTTP Proxy server.

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.

var ws = new WebSocket ("ws://example.com");
ws.SetProxy ("http://localhost:3128", "nobita", "password");

I have tested this with Squid. It's necessary to disable the following configuration option in squid.conf (e.g. /etc/squid/squid.conf).

# Deny CONNECT to other than SSL ports
#http_access deny CONNECT !SSL_ports

Logging

The WebSocket class has the own logging function.

You can use it with the WebSocket.Log property (returns a WebSocketSharp.Logger).

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.

ws.Log.Level = LogLevel.Debug;

The above means a log with lower than LogLevel.Debug cannot be outputted.

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.

ws.Log.Debug ("This is a debug message.");

The WebSocketServer and HttpServer classes have the same logging function.

Examples

Examples using websocket-sharp.

Example

Example connects to the Echo server with the WebSocket.

Example2

Example2 starts a WebSocket server.

Example3

Example3 starts an HTTP server that allows to accept the WebSocket handshake requests.

Would you access to http://localhost:4649 to do WebSocket Echo Test with your web browser while Example3 is running?

Supported WebSocket Specifications

websocket-sharp supports RFC 6455, and it's based on the following WebSocket references:

Thanks for translating to japanese.

License

websocket-sharp is provided under The MIT License.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市轨帜,隨后出現(xiàn)的幾起案子侮攀,更是在濱河造成了極大的恐慌闻伶,老刑警劉巖弛车,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渊额,死亡現(xiàn)場離奇詭異巡蘸,居然都是意外死亡它褪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來远剩,“玉大人扣溺,你說我怎么就攤上這事骇窍」衔睿” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵腹纳,是天一觀的道長痢掠。 經(jīng)常有香客問我,道長嘲恍,這世上最難降的妖魔是什么足画? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮佃牛,結(jié)果婚禮上淹辞,老公的妹妹穿的比我還像新娘。我一直安慰自己俘侠,他們只是感情好象缀,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著爷速,像睡著了一般央星。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惫东,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天莉给,我揣著相機(jī)與錄音,去河邊找鬼廉沮。 笑死颓遏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的滞时。 我是一名探鬼主播叁幢,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼漂洋!你這毒婦竟也來了遥皂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤刽漂,失蹤者是張志新(化名)和其女友劉穎演训,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贝咙,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡样悟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窟她。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陈症,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出震糖,到底是詐尸還是另有隱情录肯,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布吊说,位于F島的核電站论咏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏颁井。R本人自食惡果不足惜厅贪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雅宾。 院中可真熱鬧养涮,春花似錦、人聲如沸眉抬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吐辙。三九已至宣决,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昏苏,已是汗流浹背尊沸。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贤惯,地道東北人洼专。 一個(gè)月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像孵构,于是被迫代替她去往敵國和親屁商。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容