//笔记记录
NuGet Gallery
websocket-sharp is available on the NuGet Gallery, as still a prerelease version.
PM> Install-Package WebSocketSharp -Pre
Usage
Server端
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; using WebSocketSharp; using WebSocketSharp.Server; namespace TestWebSocketServer { public class Program { public static void Main(string[] args) { var wssv = new WebSocketServer(4396); // 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"]; //// If you would like to get the value of the Origin header included in a handshake request, /////you should access the WebSocketBehavior.Context.Origin property. ////If you would like to get the cookies included in a handshake request, /////you should access the WebSocketBehavior.Context.CookieCollection property. ///ps in Class implement WebSocketBehavior methods ///protected override void OnOpen() //{ // base.OnOpen(); // Console.WriteLine("In server OnOpen"); // var cookietest = Context.CookieCollection; // string oringteset = Context.Origin; //} // } // // ... //} //And if you would like to validate the Origin header, cookies, or both, //you should set each validation for it with your WebSocketBehavior, // for example, by using the WebSocketServer.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. } } ); */ //SSL/TLS. // As a WebSocket server, you should create a new instance of the WebSocketServer or HttpServer class with some settings for the secure connection, such as the following. //var wssv1 = new WebSocketServer(IPAddress.Parse("ws://localhost"), 5963,true); //wssv1.SslConfiguration.ServerCertificate = new X509Certificate2("/path/to/cert.pfx", "password for cert.pfx"); //public X509Certificate2(string fileName, string password); wssv.AddWebSocketService<Laputa>("/Laputa"); //HTTP Authentication //As a WebSocket server, you should set an HTTP authentication scheme, a realm, and any function to find the user credentials before calling the start method, 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 are not found. //}; //If you would like to provide the Digest authentication, you should set such as the following. //wssv.AuthenticationSchemes = AuthenticationSchemes.Digest; // notes :If you create a new instance of the WebSocketServer class without a port number, it sets the port number to 80. // So it is necessary to run with root permission. // // // 摘要: // Adds the WebSocket service with the specified behavior, path, and initializer. // // 参数: // path: // A System.String that represents the absolute path to the service to add. // // initializer: // A Func<T> delegate that references the method used to initialize a new specified // typed WebSocketSharp.Server.WebSocketBehavior instance (a new WebSocketSharp.Server.IWebSocketSession // instance). // // 类型参数: // TBehavior: // The type of the behavior of the service to add. The TBehavior must inherit the // WebSocketSharp.Server.WebSocketBehavior class. // // 言论: // This method converts path to URL-decoded string, and removes '/' from tail end // of path. // initializer returns an initialized specified typed WebSocketSharp.Server.WebSocketBehavior // instance. // public void AddWebSocketService<TBehavior>(string path, Func<TBehavior> initializer) where TBehavior : WebSocketBehavior; // Given a parameter that actually points to a new delegate //The type of TBehaviorWithNew must inherit the WebSocketBehavior class, and must have a public parameterless constructor. //The type of TBehavior must inherit the WebSocketBehavior class.(ps: Generic constraint) wssv.AddWebSocketService<Chat>("/ChatWithNyan", () => new Chat(" Nyan!")); //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>("/ExtensionsChat", () => new Chat() { // To ignore the extensions requested from a client. IgnoreExtensions = true }); wssv.Start(); Console.WriteLine("WebSocket Start"); Console.ReadKey(true); wssv.Stop(); // //You can use the WebSocketServer.Stop (), //WebSocketServer.Stop (ushort, string), //WebSocketServer.Stop (WebSocketSharp.CloseStatusCode, string) //method to stop the server. // // 摘要: // Stops receiving the WebSocket connection requests with the specified WebSocketSharp.CloseStatusCode // and System.String. // // 参数: // code: // One of the WebSocketSharp.CloseStatusCode enum values, represents the status // code indicating the reason for the stop. // // reason: // A System.String that represents the reason for the stop. //public void Stop(CloseStatusCode code, string reason); //wssv.Stop(CloseStatusCode.Normal, "test reason"); //(Words by websocket-sharp author:"https://github.com/sta/websocket-sharp")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(4397); httpsv.AddWebSocketService<Echo>("/Echo"); httpsv.AddWebSocketService<Chat>("/Chat"); httpsv.AddWebSocketService<Chat>("/ChatWithNyan", () => new Chat(" Nyan!")); } } public class Echo : WebSocketBehavior { protected override void OnMessage(MessageEventArgs e) { Console.WriteLine(DateTime.Now + " In Server Receive Message :" + e.Data); Send(e.Data); } } 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."; Console.WriteLine(DateTime.Now + " In Server Receive Message :" + e.Data); Send(msg); } } //You can define the behavior of any WebSocket service by creating the class that inherits the WebSocketBehavior class. public class Chat : WebSocketBehavior { private string _suffix; public Chat() : this(null) { } public Chat(string suffix) { _suffix = suffix ?? String.Empty; } //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. protected override void OnMessage(MessageEventArgs e) { //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.!!! in her Get WebSocketSessionManager to Broadcast Console.WriteLine(DateTime.Now+" In Server Receive Message :" + e.Data); Sessions.Broadcast(e.Data + _suffix); } //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. protected override void OnOpen() { base.OnOpen(); Console.WriteLine("In server OnOpen"); //var cookietest = Context.CookieCollection; //string oringteset= Context.Origin; } protected override void OnClose(CloseEventArgs e) { base.OnClose(e); Console.WriteLine("In server OnClose :" + e.Reason + " " + e.Code + " " + e.WasClean); } } }
Client端
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WebSocketSharp; namespace TestWebSocketClient { class Program { static void Main(string[] args) { using (var ws = new WebSocket("ws://172.16.16.82:4396/Laputa")) { //SSL/TLS. // if you would like to set a custom validation for the server certificate, you should set the WebSocket.SslConfiguration.ServerCertificateValidationCallback property to a callback for it. //ws.SslConfiguration.ServerCertificateValidationCallback = // (sender, certificate, chain, sslPolicyErrors) => { // // Do something to validate the server certificate. // // ... // return true; // If the server certificate is valid. // }; //The default callback always returns true. // HTTP Authentication //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 calling the connect method. //ws.SetCredentials("nobita", "password", preAuth); //If preAuth is true, the client will send the credentials for the Basic authentication in the first handshake request to the server. // Otherwise, it will send the credentials for either the Basic or Digest(determined by the unauthorized response to the first handshake request) authentication in the second handshake request to the server. //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 calling the connect method. */ //var ws = new WebSocket("ws://example.com"); //ws.SetProxy("http://localhost:3128", "nobita", "password"); //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. //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. ws.EmitOnPing = true; ws.OnMessage += (sender, e) => { Console.WriteLine("Laputa says: " + e.Data); Console.WriteLine("in client OnMessage"); if (e.IsText) { // Do something with e.Data. return; } if (e.IsBinary) { // Do something with e.RawData. return; } }; ws.OnOpen += (sender, e) => { Console.WriteLine("in client OnOpen"); }; ws.OnError += (sender, e) => { //... }; ws.OnClose += (sender, e) => { // ... Console.WriteLine("in client OnClose"); //e.Code property returns a ushort that represents the status code for the close. Console.WriteLine(e.Code); //e.Reason property returns a string that represents the reason for the close. Console.WriteLine(e.Reason); }; /* // websocket - sharp supports the Per - message Compression extension(but does not support it with the context take over). //compression method before calling the connect method. ws.Compression = CompressionMethod.Deflate; */ //And then the 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 supports this extension, it will return the same header which has the corresponding value. So eventually this extension will be available when the client receives the header in the handshake response. */ //Connecting to the WebSocket server. ws.Connect(); //If you would like to connect to the server asynchronously, you should use the WebSocket.ConnectAsync () method. // ws.ConnectAsync(); //Sending data to the WebSocket server. ws.Send("BALUS"); Console.WriteLine(DateTime.Now+" Sended Message!"); // 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. //// /// // 摘要: // Sends binary data asynchronously using the WebSocket connection. // // 参数: // data: // An array of System.Byte that represents the binary data to send. // // completed: // An Action<bool> delegate that references the method(s) called when the send is // complete. A System.Boolean passed to this delegate is true if the send is complete // successfully. // // 言论: // This method doesn't wait for the send to be complete. //public void SendAsync(byte[] data, Action<bool> completed); // ws.SendAsync(Encoding.UTF8.GetBytes("123456"), (a) => { Console.WriteLine("oK" + a); }); Console.ReadKey(true); //// // 摘要: // Closes the WebSocket connection with the specified WebSocketSharp.CloseStatusCode // and System.String, and releases all associated resources. // // 参数: // code: // One of the WebSocketSharp.CloseStatusCode enum values, represents the status // code indicating the reason for the close. // // reason: // A System.String that represents the reason for the close. // // 言论: // This method emits a WebSocketSharp.WebSocket.OnError event if the size of reason // is greater than 123 bytes. // public void Close(CloseStatusCode code, string reason); // ws.Close(CloseStatusCode.Normal, "test reason"); // // // 摘要: // Closes the WebSocket connection asynchronously with the specified System.UInt16 // and System.String, and releases all associated resources. // // 参数: // code: // A System.UInt16 that represents the status code indicating the reason for the // close. // // reason: // A System.String that represents the reason for the close. // // 言论: // This method doesn't wait for the close to be complete. // This method emits a WebSocketSharp.WebSocket.OnError event if code isn't in the // allowable range of the close status code or the size of reason is greater than // 123 bytes. // public void CloseAsync(ushort code, string reason); //You can use the WebSocket.Close (), //WebSocket.Close (ushort), //WebSocket.Close (WebSocketSharp.CloseStatusCode), //WebSocket.Close (ushort, string), //WebSocket.Close (WebSocketSharp.CloseStatusCode, string) //method to close the connection. //ws.CloseAsync((ushort)12, "dsasdafd"); //As a WebSocket client, if you would like to send the query string in the handshake request, you should create a new instance of the WebSocket class with a WebSocket URL that includes the Query string parameters. //var ws = new WebSocket ("ws://example.com/?name=nobita"); //If you would like to send the Origin header in the handshake request, you should set the WebSocket.Origin property to an allowable value as the Origin header before calling the connect method. //ws.Origin = "http://example.com"; //And if you would like to send the cookies in the handshake request, you should set any cookie by using the WebSocket.SetCookie(WebSocketSharp.Net.Cookie) method before calling the connect method. //ws.SetCookie(new Cookie("name", "nobita")); } } } }
License
websocket-sharp is provided under The MIT License.