diff --git a/Example/Example.pidb b/Example/Example.pidb index bd18f672..e8af61bf 100644 Binary files a/Example/Example.pidb and b/Example/Example.pidb differ diff --git a/Example/Program.cs b/Example/Program.cs index 74c26cd7..a67428cd 100644 --- a/Example/Program.cs +++ b/Example/Program.cs @@ -73,8 +73,9 @@ namespace Example ThreadPool.QueueUserWorkItem(notifyMsg); - using (WebSocket ws = new WebSocket("ws://echo.websocket.org", "echo")) + //using (WebSocket ws = new WebSocket("ws://echo.websocket.org", "echo")) //using (WebSocket ws = new WebSocket("wss://echo.websocket.org", "echo")) + using (WebSocket ws = new WebSocket("ws://localhost:4649")) { ws.OnOpen += (sender, e) => { @@ -88,7 +89,7 @@ namespace Example ws.OnError += (sender, e) => { - enNfMessage("[WebSocket] Error", e.Data, "notification-message-im"); + enNfMessage("[WebSocket] Error", e.Message, "notification-message-im"); }; ws.OnClose += (sender, e) => diff --git a/Example/bin/Debug/example.exe b/Example/bin/Debug/example.exe index 075e308f..3c76bb23 100755 Binary files a/Example/bin/Debug/example.exe and b/Example/bin/Debug/example.exe differ diff --git a/Example/bin/Debug/example.exe.mdb b/Example/bin/Debug/example.exe.mdb index 8c77fe71..80eaa185 100644 Binary files a/Example/bin/Debug/example.exe.mdb and b/Example/bin/Debug/example.exe.mdb differ diff --git a/Example/bin/Debug/websocket-sharp.dll b/Example/bin/Debug/websocket-sharp.dll index 6fd6c13b..a3c86269 100755 Binary files a/Example/bin/Debug/websocket-sharp.dll and b/Example/bin/Debug/websocket-sharp.dll differ diff --git a/Example/bin/Debug/websocket-sharp.dll.mdb b/Example/bin/Debug/websocket-sharp.dll.mdb index 695ceb15..83a06f05 100644 Binary files a/Example/bin/Debug/websocket-sharp.dll.mdb and b/Example/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example/bin/Debug_Ubuntu/example.exe b/Example/bin/Debug_Ubuntu/example.exe index 4328cab3..31b552f0 100755 Binary files a/Example/bin/Debug_Ubuntu/example.exe and b/Example/bin/Debug_Ubuntu/example.exe differ diff --git a/Example/bin/Debug_Ubuntu/example.exe.mdb b/Example/bin/Debug_Ubuntu/example.exe.mdb index 7203875e..8fb49fe8 100644 Binary files a/Example/bin/Debug_Ubuntu/example.exe.mdb and b/Example/bin/Debug_Ubuntu/example.exe.mdb differ diff --git a/Example/bin/Debug_Ubuntu/websocket-sharp.dll b/Example/bin/Debug_Ubuntu/websocket-sharp.dll index 4b8d81cb..e318f2b9 100755 Binary files a/Example/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index f26ae797..8e296ffa 100644 Binary files a/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example/bin/Release/example.exe b/Example/bin/Release/example.exe index 05a56e8d..2612eac0 100755 Binary files a/Example/bin/Release/example.exe and b/Example/bin/Release/example.exe differ diff --git a/Example/bin/Release/websocket-sharp.dll b/Example/bin/Release/websocket-sharp.dll index 0096e74e..c41cbdc8 100755 Binary files a/Example/bin/Release/websocket-sharp.dll and b/Example/bin/Release/websocket-sharp.dll differ diff --git a/Example/bin/Release_Ubuntu/example.exe b/Example/bin/Release_Ubuntu/example.exe index 4bfd5bea..cdbf41c8 100755 Binary files a/Example/bin/Release_Ubuntu/example.exe and b/Example/bin/Release_Ubuntu/example.exe differ diff --git a/Example/bin/Release_Ubuntu/websocket-sharp.dll b/Example/bin/Release_Ubuntu/websocket-sharp.dll index eed7a63f..9541e270 100755 Binary files a/Example/bin/Release_Ubuntu/websocket-sharp.dll and b/Example/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/Example1/AudioStreamer.cs b/Example1/AudioStreamer.cs index bbfbf691..3a0a6cc7 100644 --- a/Example1/AudioStreamer.cs +++ b/Example1/AudioStreamer.cs @@ -108,7 +108,7 @@ namespace Example _ws.OnError += (sender, e) => { - enNfMessage("[AudioStreamer] error", "WS: Error: " + e.Data, "notification-message-im"); + enNfMessage("[AudioStreamer] error", "WS: Error: " + e.Message, "notification-message-im"); }; _ws.OnClose += (sender, e) => diff --git a/Example1/Example1.pidb b/Example1/Example1.pidb index b5082acb..02ab1ea4 100644 Binary files a/Example1/Example1.pidb and b/Example1/Example1.pidb differ diff --git a/Example1/bin/Debug/example1.exe b/Example1/bin/Debug/example1.exe index f37ceb2b..2cfd924f 100755 Binary files a/Example1/bin/Debug/example1.exe and b/Example1/bin/Debug/example1.exe differ diff --git a/Example1/bin/Debug/example1.exe.mdb b/Example1/bin/Debug/example1.exe.mdb index 9f23f439..87d20e00 100644 Binary files a/Example1/bin/Debug/example1.exe.mdb and b/Example1/bin/Debug/example1.exe.mdb differ diff --git a/Example1/bin/Debug/websocket-sharp.dll b/Example1/bin/Debug/websocket-sharp.dll index 6fd6c13b..a3c86269 100755 Binary files a/Example1/bin/Debug/websocket-sharp.dll and b/Example1/bin/Debug/websocket-sharp.dll differ diff --git a/Example1/bin/Debug/websocket-sharp.dll.mdb b/Example1/bin/Debug/websocket-sharp.dll.mdb index 695ceb15..83a06f05 100644 Binary files a/Example1/bin/Debug/websocket-sharp.dll.mdb and b/Example1/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example1/bin/Debug_Ubuntu/example1.exe b/Example1/bin/Debug_Ubuntu/example1.exe index 3c365f20..747660a6 100755 Binary files a/Example1/bin/Debug_Ubuntu/example1.exe and b/Example1/bin/Debug_Ubuntu/example1.exe differ diff --git a/Example1/bin/Debug_Ubuntu/example1.exe.mdb b/Example1/bin/Debug_Ubuntu/example1.exe.mdb index 45364548..55757034 100644 Binary files a/Example1/bin/Debug_Ubuntu/example1.exe.mdb and b/Example1/bin/Debug_Ubuntu/example1.exe.mdb differ diff --git a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll index 4b8d81cb..e318f2b9 100755 Binary files a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index f26ae797..8e296ffa 100644 Binary files a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example1/bin/Release/example1.exe b/Example1/bin/Release/example1.exe index 137862de..cefdb422 100755 Binary files a/Example1/bin/Release/example1.exe and b/Example1/bin/Release/example1.exe differ diff --git a/Example1/bin/Release/websocket-sharp.dll b/Example1/bin/Release/websocket-sharp.dll index 0096e74e..c41cbdc8 100755 Binary files a/Example1/bin/Release/websocket-sharp.dll and b/Example1/bin/Release/websocket-sharp.dll differ diff --git a/Example1/bin/Release_Ubuntu/example1.exe b/Example1/bin/Release_Ubuntu/example1.exe index 0d09b87c..70d334fa 100755 Binary files a/Example1/bin/Release_Ubuntu/example1.exe and b/Example1/bin/Release_Ubuntu/example1.exe differ diff --git a/Example1/bin/Release_Ubuntu/websocket-sharp.dll b/Example1/bin/Release_Ubuntu/websocket-sharp.dll index eed7a63f..9541e270 100755 Binary files a/Example1/bin/Release_Ubuntu/websocket-sharp.dll and b/Example1/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/Example2/App.config b/Example2/App.config new file mode 100644 index 00000000..84bc00fa --- /dev/null +++ b/Example2/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Example2/AssemblyInfo.cs b/Example2/AssemblyInfo.cs new file mode 100644 index 00000000..6335efbf --- /dev/null +++ b/Example2/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("Example2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("sta")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/Example2/Example2.csproj b/Example2/Example2.csproj new file mode 100644 index 00000000..aee5e9bf --- /dev/null +++ b/Example2/Example2.csproj @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7} + Exe + Example2 + example2 + v3.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + + + none + false + bin\Release + prompt + 4 + true + + + true + full + false + bin\Debug_Ubuntu + DEBUG; + prompt + 4 + true + + + none + false + bin\Release_Ubuntu + prompt + 4 + true + + + + + + + + + + + + {B357BAC7-529E-4D81-A0D2-71041B19C8DE} + websocket-sharp + + + + + + \ No newline at end of file diff --git a/Example2/Example2.pidb b/Example2/Example2.pidb new file mode 100644 index 00000000..9dd560e7 Binary files /dev/null and b/Example2/Example2.pidb differ diff --git a/Example2/Program.cs b/Example2/Program.cs new file mode 100644 index 00000000..9a59dcc4 --- /dev/null +++ b/Example2/Program.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading; +using WebSocketSharp; + +namespace Example +{ + public class Program + { + public static void Main (string[] args) + { + //WebSocketServer wssv = new WebSocketServer("ws://localhost"); + WebSocketServer wssv = new WebSocketServer("ws://localhost:4649"); + + wssv.OnConnection += (sender, e) => + { + WebSocket ws = e.Socket; + ws.OnMessage += (sender_, e_) => + { + // Echo + ws.Send(e_.Data); + // Chat + //wssv.Send(e_.Data); + }; + }; + + wssv.Start(); + Console.WriteLine( + "WebSocket Server ({0}) listening on address: {1} port: {2}\n", wssv.Url, wssv.Address, wssv.Port); + + Console.WriteLine("Press any key to stop server..."); + Console.ReadLine(); + + wssv.Stop(); + } + } +} diff --git a/Example2/bin/Debug/example2.exe b/Example2/bin/Debug/example2.exe new file mode 100755 index 00000000..ff910fb1 Binary files /dev/null and b/Example2/bin/Debug/example2.exe differ diff --git a/Example2/bin/Debug/example2.exe.config b/Example2/bin/Debug/example2.exe.config new file mode 100644 index 00000000..84bc00fa --- /dev/null +++ b/Example2/bin/Debug/example2.exe.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Example2/bin/Debug/example2.exe.mdb b/Example2/bin/Debug/example2.exe.mdb new file mode 100644 index 00000000..657a1457 Binary files /dev/null and b/Example2/bin/Debug/example2.exe.mdb differ diff --git a/Example2/bin/Debug/websocket-sharp.dll b/Example2/bin/Debug/websocket-sharp.dll new file mode 100755 index 00000000..a3c86269 Binary files /dev/null and b/Example2/bin/Debug/websocket-sharp.dll differ diff --git a/Example2/bin/Debug/websocket-sharp.dll.mdb b/Example2/bin/Debug/websocket-sharp.dll.mdb new file mode 100644 index 00000000..83a06f05 Binary files /dev/null and b/Example2/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example2/bin/Debug_Ubuntu/example2.exe b/Example2/bin/Debug_Ubuntu/example2.exe new file mode 100755 index 00000000..53a99ad6 Binary files /dev/null and b/Example2/bin/Debug_Ubuntu/example2.exe differ diff --git a/Example2/bin/Debug_Ubuntu/example2.exe.config b/Example2/bin/Debug_Ubuntu/example2.exe.config new file mode 100644 index 00000000..84bc00fa --- /dev/null +++ b/Example2/bin/Debug_Ubuntu/example2.exe.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Example2/bin/Debug_Ubuntu/example2.exe.mdb b/Example2/bin/Debug_Ubuntu/example2.exe.mdb new file mode 100644 index 00000000..f535430b Binary files /dev/null and b/Example2/bin/Debug_Ubuntu/example2.exe.mdb differ diff --git a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll new file mode 100755 index 00000000..e318f2b9 Binary files /dev/null and b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb new file mode 100644 index 00000000..8e296ffa Binary files /dev/null and b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example2/bin/Release/example2.exe b/Example2/bin/Release/example2.exe new file mode 100755 index 00000000..9c802bce Binary files /dev/null and b/Example2/bin/Release/example2.exe differ diff --git a/Example2/bin/Release/example2.exe.config b/Example2/bin/Release/example2.exe.config new file mode 100644 index 00000000..84bc00fa --- /dev/null +++ b/Example2/bin/Release/example2.exe.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Example2/bin/Release/websocket-sharp.dll b/Example2/bin/Release/websocket-sharp.dll new file mode 100755 index 00000000..c41cbdc8 Binary files /dev/null and b/Example2/bin/Release/websocket-sharp.dll differ diff --git a/Example2/bin/Release_Ubuntu/example2.exe b/Example2/bin/Release_Ubuntu/example2.exe new file mode 100755 index 00000000..febb55f2 Binary files /dev/null and b/Example2/bin/Release_Ubuntu/example2.exe differ diff --git a/Example2/bin/Release_Ubuntu/example2.exe.config b/Example2/bin/Release_Ubuntu/example2.exe.config new file mode 100644 index 00000000..84bc00fa --- /dev/null +++ b/Example2/bin/Release_Ubuntu/example2.exe.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Example2/bin/Release_Ubuntu/websocket-sharp.dll b/Example2/bin/Release_Ubuntu/websocket-sharp.dll new file mode 100755 index 00000000..9541e270 Binary files /dev/null and b/Example2/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/README.md b/README.md index 01fc1e6d..eebd208a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ # websocket-sharp # -**websocket-sharp** is a C# implementation of a WebSocket protocol client. +**websocket-sharp** is a C# implementation of a WebSocket protocol client & server. ## Usage ## -### Step 1 ### +### WebSocket Client ### + +#### Step 1 #### Required namespaces. @@ -13,7 +15,7 @@ Required namespaces. In `WebSocketSharp` namespace `WebSocket` class exists, in `WebSocketSharp.Frame` namespace WebSocket data frame resources (e.g. `WsFrame` class) exist. -### Step 2 ### +#### Step 2 #### Creating instance of `WebSocket` class. @@ -22,13 +24,13 @@ Creating instance of `WebSocket` class. ... } -So `WebSocket` class inherits `IDisposable` interface, you can use `using` statement. +`WebSocket` class inherits `IDisposable` interface, so you can use `using` statement. -### Step 3 ### +#### Step 3 #### Setting `WebSocket` event handlers. -#### WebSocket.OnOpen event #### +##### WebSocket.OnOpen event ##### `WebSocket.OnOpen` event is emitted immediately after WebSocket connection has been established. @@ -37,9 +39,9 @@ Setting `WebSocket` event handlers. ... }; -So `e` has come across as `EventArgs.Empty`, there is no operation on `e`. +`e` has come across as `EventArgs.Empty`, so there is no operation on `e`. -#### WebSocket.OnMessage event #### +##### WebSocket.OnMessage event ##### `WebSocket.OnMessage` event is emitted each time WebSocket data frame is received. @@ -48,7 +50,7 @@ So `e` has come across as `EventArgs.Empty`, there is no operation on `e`. ... }; -So **type** of received WebSocket data frame is stored in `e.Type` (`WebSocketSharp.MessageEventArgs.Type`, its type is `WebSocketSharp.Frame.Opcode`), you check it out and you determine which item you should operate. +**type** of received WebSocket data frame is stored in `e.Type` (`WebSocketSharp.MessageEventArgs.Type`, its type is `WebSocketSharp.Frame.Opcode`), so you check it out and you determine which item you should operate. switch (e.Type) { @@ -66,7 +68,7 @@ If `e.Type` is `Opcode.TEXT`, you operate `e.Data` (`WebSocketSharp.MessageEvent If `e.Type` is `Opcode.BINARY`, you operate `e.RawData` (`WebSocketSharp.MessageEventArgs.RawData`, its type is `byte[]`). -#### WebSocket.OnError event #### +##### WebSocket.OnError event ##### `WebSocket.OnError` event is emitted when some error is occurred. @@ -75,9 +77,9 @@ If `e.Type` is `Opcode.BINARY`, you operate `e.RawData` (`WebSocketSharp.Message ... }; -So error message is stored in `e.Data` (`WebSocketSharp.MessageEventArgs.Data`, its type is `string`), you operate it. +Error message is stored in `e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, its type is `string`), so you operate it. -#### WebSocket.OnClose event #### +##### WebSocket.OnClose event ##### `WebSocket.OnClose` event is emitted when WebSocket connection is closed. @@ -86,15 +88,15 @@ So error message is stored in `e.Data` (`WebSocketSharp.MessageEventArgs.Data`, ... }; -So close status code is stored in `e.Code` (`WebSocketSharp.CloseEventArgs.Code`, its type is `WebSocketSharp.Frame.CloseStatusCode`) and reason of close is stored in `e.Reason` (`WebSocketSharp.CloseEventArgs.Reason`, its type is `string`), you operate them. +Close status code is stored in `e.Code` (`WebSocketSharp.CloseEventArgs.Code`, its type is `WebSocketSharp.Frame.CloseStatusCode`) and reason of close is stored in `e.Reason` (`WebSocketSharp.CloseEventArgs.Reason`, its type is `string`), so you operate them. -### Step 4 ### +#### Step 4 #### Connecting to server using WebSocket. ws.Connect(); -### Step 5 ### +#### Step 5 #### Sending data. @@ -104,7 +106,7 @@ Sending data. `data` types are `string`, `byte[]` and `FileInfo` class. -### Step 6 ### +#### Step 6 #### Closing WebSocket connection. @@ -116,6 +118,96 @@ Type of `code` is `WebSocketSharp.Frame.CloseStatusCode`, type of `reason` is `s `WebSocket.Close` method is overloaded (In addition `Close()` and `Close(code)` exist). +### WebSocket Server ### + +#### Step 1 #### + +Required namespaces. + + using WebSocketSharp; + using WebSocketSharp.Frame; + +Same as **WebSocket Client**. + +#### Step 2 #### + +Creating instance of `WebSocketServer` class. + + WebSocketServer wssv = new WebSocketServer("ws://example.com:4649"); + +If you set WebSocket url without port number, `WebSocketServer` set 80 or 443 to port number automatically. +So it is necessary to run with root permission. + + $ sudo mono example2.exe + +#### Step 3 #### + +Setting WebSocketServer event handlers. + +##### WebSocketServer.OnConnection event ##### + +`WebSocketServer.OnConnection` event is emitted each time client makes a connection request. + + wssv.OnConnection += (sender, e) => + { + ... + }; + +`WebSocket` to communicate with client is stored in `e.Socket` (`WebSocketSharp.ConnectionEventArgs.Socket`, its type is `WebSocketSharp.WebSocket`), so you operate it. + + WebSocket ws = e.Socket; + ws.OnMessage += (sender_, e_) => + { + ... + }; + +Same settings of `WebSocket` event handlers as **WebSocket Client**. + +This WebSocket is server-side, so data is sent from server to client. + +If you want to function as echo server that returns a data to client as it is received, + + // Echo + ws.Send(e_.Data); + +If you want to function as chat server that returns a data to all clients, + + // Chat + wssv.Send(e_.Data); + +##### WebSocketServer.OnError event ##### + +`WebSocketServer.OnError` event is emitted when some error is occurred. + + wssv.OnError += (sender, e) => + { + ... + }; + +Error message is stored in `e.Message` (`WebSocketSharp.ErrorEventArgs.Message`, its type is `string`), so you operate it. + +#### Step 4 #### + +Starting server. + + wssv.Start(); + +#### Step 5 #### + +Sending data to all clients. + + wssv.Send(data); + +`WebSocketServer.Send` method is overloaded. + +`data` types are `string` and `byte[]`. + +#### Step 6 #### + +Stopping server. + + wssv.Stop(); + ## Examples ## Examples of using **websocket-sharp**. @@ -130,6 +222,10 @@ Examples of using **websocket-sharp**. [Example1] uses [Json.NET]. +### Example2 ### + +[Example2] starts WebSocket server. + ## Supported WebSocket Protocol ## **websocket-sharp** supports **[RFC 6455]**. @@ -160,6 +256,7 @@ Licensed under the **[MIT License]**. [Echo server]: http://www.websocket.org/echo.html [Example]: https://github.com/sta/websocket-sharp/tree/master/Example [Example1]: https://github.com/sta/websocket-sharp/tree/master/Example1 +[Example2]: https://github.com/sta/websocket-sharp/tree/master/Example2 [hixie-75]: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 [hybi-00]: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00 [Json.NET]: http://james.newtonking.com/projects/json-net.aspx diff --git a/websocket-sharp.sln b/websocket-sharp.sln index a7c94077..ef2da1cf 100644 --- a/websocket-sharp.sln +++ b/websocket-sharp.sln @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example1", "Example1\Example1.csproj", "{390E2568-57B7-4D17-91E5-C29336368CCF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example2", "Example2\Example2.csproj", "{B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,14 @@ Global {B357BAC7-529E-4D81-A0D2-71041B19C8DE}.Release_Ubuntu|Any CPU.Build.0 = Release_Ubuntu|Any CPU {B357BAC7-529E-4D81-A0D2-71041B19C8DE}.Release|Any CPU.ActiveCfg = Release|Any CPU {B357BAC7-529E-4D81-A0D2-71041B19C8DE}.Release|Any CPU.Build.0 = Release|Any CPU + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug_Ubuntu|Any CPU + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}.Debug_Ubuntu|Any CPU.Build.0 = Debug_Ubuntu|Any CPU + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}.Release_Ubuntu|Any CPU.ActiveCfg = Release_Ubuntu|Any CPU + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}.Release_Ubuntu|Any CPU.Build.0 = Release_Ubuntu|Any CPU + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B81A24C8-25BB-42B2-AF99-1E1EACCE74C7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = websocket-sharp\websocket-sharp.csproj diff --git a/websocket-sharp.userprefs b/websocket-sharp.userprefs index cb5cca4b..8d2074ef 100644 --- a/websocket-sharp.userprefs +++ b/websocket-sharp.userprefs @@ -2,7 +2,7 @@ - + diff --git a/websocket-sharp/ConnectionEventArgs.cs b/websocket-sharp/ConnectionEventArgs.cs new file mode 100644 index 00000000..9b2c3615 --- /dev/null +++ b/websocket-sharp/ConnectionEventArgs.cs @@ -0,0 +1,42 @@ +#region MIT License +/** + * ConnectionEventArgs.cs + * + * The MIT License + * + * Copyright (c) 2012 sta.blockhead + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#endregion + +using System; + +namespace WebSocketSharp +{ + public class ConnectionEventArgs : EventArgs + { + public WebSocket Socket { get; private set; } + + public ConnectionEventArgs(WebSocket webSocket) + { + Socket = webSocket; + } + } +} diff --git a/websocket-sharp/ErrorEventArgs.cs b/websocket-sharp/ErrorEventArgs.cs new file mode 100644 index 00000000..0f7c8d5c --- /dev/null +++ b/websocket-sharp/ErrorEventArgs.cs @@ -0,0 +1,42 @@ +#region MIT License +/** + * ErrorEventArgs.cs + * + * The MIT License + * + * Copyright (c) 2012 sta.blockhead + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#endregion + +using System; + +namespace WebSocketSharp +{ + public class ErrorEventArgs : EventArgs + { + public string Message { get; private set; } + + public ErrorEventArgs(string message) + { + Message = message; + } + } +} diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 8f47db3f..8bc6157a 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; +using System.Configuration; using System.Diagnostics; using System.IO; using System.Linq; @@ -60,12 +61,14 @@ namespace WebSocketSharp #region Private Fields + private AutoResetEvent _autoEvent; private string _base64key; private string _binaryType; private string _extensions; private Object _forClose; private Object _forSend; private int _fragmentLen; + private bool _isClient; private Thread _msgThread; private NetworkStream _netStream; private string _protocol; @@ -125,7 +128,7 @@ namespace WebSocketSharp switch (value) { case WsState.OPEN: - messageThreadStart(); + startMessageThread(); OnOpen.Emit(this, EventArgs.Empty); break; case WsState.CLOSING: @@ -153,7 +156,7 @@ namespace WebSocketSharp public event EventHandler OnOpen; public event EventHandler OnMessage; - public event EventHandler OnError; + public event EventHandler OnError; public event EventHandler OnClose; #endregion @@ -174,27 +177,43 @@ namespace WebSocketSharp #endregion + #region Internal Constructors + + internal WebSocket(string url, TcpClient tcpClient) + : this() + { + _uri = new Uri(url); + if (!isValidScheme(_uri)) + { + throw new ArgumentException("Unsupported WebSocket URI scheme: " + _uri.Scheme); + } + + _tcpClient = tcpClient; + _isClient = false; + } + + #endregion + #region Public Constructors public WebSocket(string url, params string[] protocols) - : this() + : this() { - _uri = new Uri(url); - string scheme = _uri.Scheme; - - if (scheme != "ws" && scheme != "wss") + _uri = new Uri(url); + if (!isValidScheme(_uri)) { - throw new ArgumentException("Unsupported WebSocket URI scheme: " + scheme); + throw new ArgumentException("Unsupported WebSocket URI scheme: " + _uri.Scheme); } - _protocols = protocols.ToString(", "); + _protocols = protocols.ToString(", "); + _isClient = true; } public WebSocket( string url, EventHandler onOpen, EventHandler onMessage, - EventHandler onError, + EventHandler onError, EventHandler onClose, params string[] protocols) : this(url, protocols) @@ -211,10 +230,37 @@ namespace WebSocketSharp #region Private Methods + private void acceptHandshake() + { + string msg, response; + string[] request; + + request = receiveOpeningHandshake(); + #if DEBUG + Console.WriteLine("\nWS: Info@acceptHandshake: Opening handshake from client:\n"); + foreach (string s in request) + { + Console.WriteLine("{0}", s); + } + #endif + if (!isValidRequest(request, out msg)) + { + throw new InvalidOperationException(msg); + } + + response = createResponseHandshake(); + #if DEBUG + Console.WriteLine("\nWS: Info@acceptHandshake: Opening handshake from server:\n{0}", response); + #endif + sendResponseHandshake(response); + + ReadyState = WsState.OPEN; + } + private void close(PayloadData data) { #if DEBUG - Console.WriteLine("WS: Info@close: Current thread IsBackground?: {0}", Thread.CurrentThread.IsBackground); + Console.WriteLine("\nWS: Info@close: Current thread IsBackground?: {0}", Thread.CurrentThread.IsBackground); #endif lock(_forClose) { @@ -291,13 +337,20 @@ namespace WebSocketSharp if (!Thread.CurrentThread.IsBackground) { - _msgThread.Join(5000); + if (_isClient) + { + _msgThread.Join(5000); + } + else + { + _autoEvent.WaitOne(); + } } ReadyState = WsState.CLOSED; } - private void createConnection() + private void createClientStream() { string scheme = _uri.Scheme; string host = _uri.DnsSafeHost; @@ -400,6 +453,45 @@ namespace WebSocketSharp crlf; } + private string createResponseHandshake() + { + string crlf = "\r\n"; + + string resStatus = "HTTP/1.1 101 Switching Protocols" + crlf; + string resUpgrade = "Upgrade: websocket" + crlf; + string resConnection = "Connection: Upgrade" + crlf; + string secWsAccept = String.Format("Sec-WebSocket-Accept: {0}{1}", createExpectedKey(), crlf); + //string secWsProtocol = "Sec-WebSocket-Protocol: chat" + crlf; + string secWsVersion = String.Format("Sec-WebSocket-Version: {0}{1}", _version, crlf); + + return resStatus + + resUpgrade + + resConnection + + secWsAccept + + //secWsProtocol + + secWsVersion + + crlf; + } + + private void createServerStream() + { + _netStream = _tcpClient.GetStream(); + + if (_uri.Scheme == "wss") + { + _sslStream = new SslStream(_netStream); + + string certPath = ConfigurationManager.AppSettings["ServerCertPath"]; + _sslStream.AuthenticateAsServer(new X509Certificate(certPath)); + + _wsStream = new WsStream(_sslStream); + } + else + { + _wsStream = new WsStream(_netStream); + } + } + private void doHandshake() { string msg, request; @@ -407,11 +499,11 @@ namespace WebSocketSharp request = createOpeningHandshake(); #if DEBUG - Console.WriteLine("WS: Info@doHandshake: Opening handshake from client:\n{0}", request); + Console.WriteLine("\nWS: Info@doHandshake: Opening handshake from client:\n{0}", request); #endif response = sendOpeningHandshake(request); #if DEBUG - Console.WriteLine("WS: Info@doHandshake: Opening handshake from server:"); + Console.WriteLine("\nWS: Info@doHandshake: Opening handshake from server:\n"); foreach (string s in response) { Console.WriteLine("{0}", s); @@ -432,18 +524,123 @@ namespace WebSocketSharp var caller = callerFrame.GetMethod(); Console.WriteLine("WS: Error@{0}: {1}", caller.Name, message); #endif - OnError.Emit(this, new MessageEventArgs(message)); + OnError.Emit(this, new ErrorEventArgs(message)); + } + + private bool isValidRequest(string[] request, out string message) + { + string reqConnection, reqHost, reqUpgrade, secWsVersion; + string[] reqRequest; + + List extensionList = new List(); + + Func> func = s => + { + return (e, a) => + { + return String.Format("Invalid request {0} value: {1}(expected: {2})", s, a, e); + }; + }; + + string expectedHost = _uri.DnsSafeHost; + int port = ((IPEndPoint)_tcpClient.Client.LocalEndPoint).Port; + if (port != 80) + { + expectedHost += ":" + port; + } + + reqRequest = request[0].Split(' '); + if ("GET".NotEqualsDo(reqRequest[0], func("HTTP Method"), out message, false)) + { + return false; + } + if ("HTTP/1.1".NotEqualsDo(reqRequest[2], func("HTTP Version"), out message, false)) + { + return false; + } + + for (int i = 1; i < request.Length; i++) + { + if (request[i].Contains("Connection:")) + { + reqConnection = request[i].GetHeaderValue(":"); + if ("Upgrade".NotEqualsDo(reqConnection, func("Connection"), out message, true)) + { + return false; + } + } + else if (request[i].Contains("Host:")) + { + reqHost = request[i].GetHeaderValue(":"); + if (expectedHost.NotEqualsDo(reqHost, func("Host"), out message, true)) + { + return false; + } + } + else if (request[i].Contains("Origin:")) + { + continue; + } + else if (request[i].Contains("Upgrade:")) + { + reqUpgrade = request[i].GetHeaderValue(":"); + if ("websocket".NotEqualsDo(reqUpgrade, func("Upgrade"), out message, true)) + { + return false; + } + } + else if (request[i].Contains("Sec-WebSocket-Extensions:")) + { + extensionList.Add(request[i].GetHeaderValue(":")); + } + else if (request[i].Contains("Sec-WebSocket-Key:")) + { + _base64key = request[i].GetHeaderValue(":"); + } + else if (request[i].Contains("Sec-WebSocket-Protocol:")) + { + _protocols = request[i].GetHeaderValue(":"); + #if DEBUG + Console.WriteLine("WS: Info@isValidRequest: Sub protocol: {0}", _protocols); + #endif + } + else if (request[i].Contains("Sec-WebSocket-Version:")) + { + secWsVersion = request[i].GetHeaderValue(":"); + if (_version.NotEqualsDo(secWsVersion, func("Sec-WebSocket-Version"), out message, true)) + { + return false; + } + } + else + { + Console.WriteLine("WS: Info@isValidRequest: Unsupported request header line: {0}", request[i]); + } + } + + if (String.IsNullOrEmpty(_base64key)) + { + message = "Sec-WebSocket-Key header field does not exist or the value isn't set."; + return false; + } + #if DEBUG + foreach (string s in extensionList) + { + Console.WriteLine("WS: Info@isValidRequest: Extensions: {0}", s); + } + #endif + message = String.Empty; + return true; } private bool isValidResponse(string[] response, out string message) { - Func> func; - string resUpgrade, resConnection; - string secWsAccept, secWsVersion; + string resUpgrade, resConnection, secWsAccept, secWsVersion; string[] resStatus; + List extensionList = new List(); - func = s => + Func> func = s => { return (e, a) => { @@ -501,9 +698,10 @@ namespace WebSocketSharp else if (response[i].Contains("Sec-WebSocket-Version:")) { secWsVersion = response[i].GetHeaderValue(":"); - #if DEBUG - Console.WriteLine("WS: Info@isValidResponse: Version: {0}", secWsVersion); - #endif + if (_version.NotEqualsDo(secWsVersion, func("Sec-WebSocket-Version"), out message, true)) + { + return false; + } } else { @@ -520,38 +718,81 @@ namespace WebSocketSharp return true; } + private bool isValidScheme(Uri uri) + { + string scheme = uri.Scheme; + if (scheme == "ws" || scheme == "wss") + { + return true; + } + + return false; + } + private void message() { - #if DEBUG - Console.WriteLine("WS: Info@message: Current thread IsBackground?: {0}", Thread.CurrentThread.IsBackground); - #endif - MessageEventArgs eventArgs; - while (_readyState == WsState.OPEN) + try { - try - { - eventArgs = receive(); + MessageEventArgs eventArgs = receive(); - if (eventArgs != null) - { - OnMessage.Emit(this, eventArgs); - } - } - catch (WsReceivedTooBigMessageException ex) + if (eventArgs != null) { - close(CloseStatusCode.TOO_BIG, ex.Message); + OnMessage.Emit(this, eventArgs); } } + catch (WsReceivedTooBigMessageException ex) + { + close(CloseStatusCode.TOO_BIG, ex.Message); + } + } + + private void messageLoop() + { + #if DEBUG + Console.WriteLine("\nWS: Info@messageLoop: Current thread IsBackground?: {0}", Thread.CurrentThread.IsBackground); + #endif + while (_readyState == WsState.OPEN) + { + message(); + } #if DEBUG - Console.WriteLine("WS: Info@message: Exit message method."); + Console.WriteLine("WS: Info@messageLoop: Exit messageLoop method."); #endif } - private void messageThreadStart() + private void startMessageThread() { - _msgThread = new Thread(new ThreadStart(message)); - _msgThread.IsBackground = true; - _msgThread.Start(); + if (_isClient) + { + _msgThread = new Thread(new ThreadStart(messageLoop)); + _msgThread.IsBackground = true; + _msgThread.Start(); + } + else + { + _autoEvent = new AutoResetEvent(false); + Action act = () => + { + if (_readyState == WsState.OPEN) + { + message(); + } + }; + AsyncCallback callback = (ar) => + { + act.EndInvoke(ar); + + if (_readyState == WsState.OPEN) + { + act.BeginInvoke(callback, null); + } + else + { + _autoEvent.Set(); + } + }; + act.BeginInvoke(callback, null); + } } private MessageEventArgs receive() @@ -671,6 +912,26 @@ namespace WebSocketSharp pong(payloadData); } + private string[] receiveOpeningHandshake() + { + var readData = new List(); + + while (true) + { + if (_wsStream.ReadByte().EqualsAndSaveTo('\r', readData) && + _wsStream.ReadByte().EqualsAndSaveTo('\n', readData) && + _wsStream.ReadByte().EqualsAndSaveTo('\r', readData) && + _wsStream.ReadByte().EqualsAndSaveTo('\n', readData)) + { + break; + } + } + + return Encoding.UTF8.GetString(readData.ToArray()) + .Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n') + .Split('\n'); + } + private bool send(WsFrame frame) { if (_readyState != WsState.OPEN) @@ -832,6 +1093,12 @@ namespace WebSocketSharp .Split('\n'); } + private void sendResponseHandshake(string value) + { + var buffer = Encoding.UTF8.GetBytes(value); + _wsStream.Write(buffer, 0, buffer.Length); + } + #endregion #region Public Methods @@ -840,14 +1107,22 @@ namespace WebSocketSharp { if (_readyState == WsState.OPEN) { - Console.WriteLine("WS: Info@Connect: Connection is already established."); + Console.WriteLine("\nWS: Info@Connect: Connection is already established."); return; } try - { - createConnection(); - doHandshake(); + { + if (_isClient) + { + createClientStream(); + doHandshake(); + } + else + { + createServerStream(); + acceptHandshake(); + } } catch (Exception ex) { diff --git a/websocket-sharp/WebSocketServer.cs b/websocket-sharp/WebSocketServer.cs new file mode 100644 index 00000000..1d1677e5 --- /dev/null +++ b/websocket-sharp/WebSocketServer.cs @@ -0,0 +1,237 @@ +#region MIT License +/** + * WebSocketServer.cs + * + * A C# implementation of a WebSocket protocol server. + * + * The MIT License + * + * Copyright (c) 2012 sta.blockhead + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using WebSocketSharp.Frame; + +namespace WebSocketSharp +{ + public class WebSocketServer + { + #region Private Fields + + private TcpListener _tcpListener; + private Uri _uri; + private SynchronizedCollection _webSockets; + + #endregion + + #region Properties + + public IPAddress Address + { + get { return Endpoint.Address; } + } + + public IPEndPoint Endpoint + { + get { return (IPEndPoint)_tcpListener.LocalEndpoint; } + } + + public int Port + { + get { return Endpoint.Port; } + } + + public string Url + { + get { return _uri.ToString(); } + } + + #endregion + + #region Events + + public event EventHandler OnConnection; + public event EventHandler OnError; + + #endregion + + #region Public Constructor + + public WebSocketServer(string url) + { + _uri = new Uri(url); + if (!isValidScheme(_uri)) + { + throw new ArgumentException("Unsupported WebSocket URI scheme: " + _uri.Scheme); + } + + string scheme = _uri.Scheme; + int port = _uri.Port; + + if (port <= 0) + { + if (scheme == "wss") + { + port = 443; + } + else + { + port = 80; + } + } + + _tcpListener = new TcpListener(IPAddress.Any, port); + _webSockets = new SynchronizedCollection(); + } + + #endregion + + #region Private Methods + + private void acceptClient(IAsyncResult ar) + { + TcpListener listener = (TcpListener)ar.AsyncState; + + if (listener.Server == null || !listener.Server.IsBound) + { + return; + } + + try + { + TcpClient client = listener.EndAcceptTcpClient(ar); + + WebSocket ws = new WebSocket(_uri.ToString(), client); + OnConnection.Emit(this, new ConnectionEventArgs(ws)); + _webSockets.Add(ws); + + ws.Connect(); + } + catch (ObjectDisposedException) + { + // TcpListener has been stopped. + return; + } + catch (Exception ex) + { + error(ex.Message); + } + + listener.BeginAcceptTcpClient(acceptClient, listener); + } + + private void error(string message) + { + #if DEBUG + var callerFrame = new StackFrame(1); + var caller = callerFrame.GetMethod(); + Console.WriteLine("WSSV: Error@{0}: {1}", caller.Name, message); + #endif + OnError.Emit(this, new ErrorEventArgs(message)); + } + + private bool isValidScheme(Uri uri) + { + string scheme = uri.Scheme; + if (scheme == "ws" || scheme == "wss") + { + return true; + } + + return false; + } + + #endregion + + #region Public Methods + + public void Close(CloseStatusCode code, string reason) + { + lock (_webSockets.SyncRoot) + { + foreach (WebSocket ws in _webSockets) + { + if (ws.ReadyState == WsState.OPEN) + { + ws.Close(code, reason); + } + } + } + } + + public void Send(byte[] data) + { + WaitCallback broadcast = (state) => + { + lock (_webSockets.SyncRoot) + { + foreach (WebSocket ws in _webSockets) + { + if (ws.ReadyState == WsState.OPEN) + { + ws.Send(data); + } + } + } + }; + ThreadPool.QueueUserWorkItem(broadcast); + } + + public void Send(string data) + { + WaitCallback broadcast = (state) => + { + lock (_webSockets.SyncRoot) + { + foreach (WebSocket ws in _webSockets) + { + if (ws.ReadyState == WsState.OPEN) + { + ws.Send(data); + } + } + } + }; + ThreadPool.QueueUserWorkItem(broadcast); + } + + public void Start() + { + _tcpListener.Start(); + _tcpListener.BeginAcceptTcpClient(acceptClient, _tcpListener); + } + + public void Stop() + { + _tcpListener.Stop(); + Close(CloseStatusCode.NORMAL, String.Empty); + } + + #endregion + } +} diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll b/websocket-sharp/bin/Debug/websocket-sharp.dll index 6fd6c13b..a3c86269 100755 Binary files a/websocket-sharp/bin/Debug/websocket-sharp.dll and b/websocket-sharp/bin/Debug/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb b/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb index 695ceb15..83a06f05 100644 Binary files a/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb and b/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll index 4b8d81cb..e318f2b9 100755 Binary files a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll and b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index f26ae797..8e296ffa 100644 Binary files a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/websocket-sharp/bin/Release/websocket-sharp.dll b/websocket-sharp/bin/Release/websocket-sharp.dll index 0096e74e..c41cbdc8 100755 Binary files a/websocket-sharp/bin/Release/websocket-sharp.dll and b/websocket-sharp/bin/Release/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll index eed7a63f..9541e270 100755 Binary files a/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll and b/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/websocket-sharp.csproj b/websocket-sharp/websocket-sharp.csproj index 6dfbe2f3..f55abe96 100644 --- a/websocket-sharp/websocket-sharp.csproj +++ b/websocket-sharp/websocket-sharp.csproj @@ -53,11 +53,11 @@ + - @@ -72,6 +72,10 @@ + + + + diff --git a/websocket-sharp/websocket-sharp.pidb b/websocket-sharp/websocket-sharp.pidb index ba958474..b0b7ab54 100644 Binary files a/websocket-sharp/websocket-sharp.pidb and b/websocket-sharp/websocket-sharp.pidb differ