/// <summary> /// The Write /// </summary> /// <param name="client">The client<see cref="WebSocketClient"/></param> /// <param name="message">The message<see cref="string"/></param> /// <returns>The <see cref="bool"/></returns> public bool Write(WebSocketClient client, string message) { try { var nextValue = Encoding.UTF8.GetBytes(message); byte[] send = new byte[2 + nextValue.Length]; send[0] = 0x80 + 0x1; // last frame, text send[1] = BitConverter.GetBytes(nextValue.Length)[0]; // not masked for (var i = 0; i < nextValue.Length; i++) { send[2 + i] = nextValue[i]; } return(writeDataInStream(client.Stream, send)); } catch (Exception e) { return(false); } }
/// <summary> /// The Start /// </summary> /// <param name="port">The port<see cref="int"/></param> /// <returns>The <see cref="Task"/></returns> public async Task Start(int port = 8990) { Port = port; if (started) { Console.WriteLine("WebSocket server already started"); return; } started = true; TcpListener listener = new TcpListener(IPAddress.Any, port); listener.Start(); Console.WriteLine("WebSocket server started"); while (true) { Console.WriteLine("Waiting for new connection.."); var client = new WebSocketClient(await listener.AcceptTcpClientAsync()); m_connectedClients.Add(client); Console.WriteLine($"New client from {client.RemoteEndPoint}"); Console.WriteLine($"Actually there are {m_connectedClients.Count} connected"); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Factory.StartNew(() => { client.Handshake += onClientHandshake; client.Message += onClientMessage; client.StartListen().ContinueWith((o) => { m_connectedClients.Remove(client); client.Dispose(); Console.WriteLine($"Client removed, now there are {m_connectedClients.Count} connected"); }); }); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } }
/// <summary> /// The sendData /// </summary> /// <param name="client">The client<see cref="WebSocketClient"/></param> internal static void sendData(WebSocketClient client) { if (m_registeredClient.Contains(client.Id)) { #if FULL_LOG Console.WriteLine($"Client {client.Id} already registered"); #endif return; } var rng = new Random(); m_registeredClient.Add(client.Id); while (m_registeredClient.Contains(client.Id)) { if (!WebSocketServer.Istance.Write(client, rng.Next(1, 100).ToString())) { return; } Thread.Sleep(1000 / 15); } }
/// <summary> /// The onClientMessage /// </summary> /// <param name="sender">The sender<see cref="WebSocketClient"/></param> /// <param name="e">The e<see cref="WebSocketDataEventArgs"/></param> private void onClientMessage(WebSocketClient sender, WebSocketDataEventArgs e) { /* * Parse message as described in * https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server#collapse-3 */ var byte1 = e.Data[0]; // should be 129 for text var received = getBytesBit(byte1); var opCode = convertBitArrayToNumber(new[] { received[4], received[5], received[6], received[7] }); #if FULL_LOG Console.WriteLine($"{received[0]} - FIN"); Console.WriteLine($"{received[1]} - RSV1"); Console.WriteLine($"{received[2]} - RSV2"); Console.WriteLine($"{received[3]} - RSV3"); Console.WriteLine($"{opCode} - Opcode"); #endif try { switch (opCode) { case 0x0: Console.WriteLine($"Received unmanaged `binary` from client {sender.RemoteEndPoint}"); break; // denotes a continuation frame case 0x1: // denotes a text frame Console.WriteLine($"Received `text` from client {sender.RemoteEndPoint}"); manageTextReceived(sender, e.Data); break; case 0x2: break; // reserved for further non-control frames case 0x3: break; case 0x4: break; case 0x5: break; case 0x6: break; case 0x7: break; case 0x8: Console.WriteLine($"Received `close connection` from client {sender.RemoteEndPoint}"); sender.Dispose(); break; // denotes a connection close case 0x9: Console.WriteLine($"Received `ping` from client {sender.RemoteEndPoint}, send `pong`"); SendPong(sender); break; // denotes a ping case 0xA: Console.WriteLine($"Received `pong` from client {sender.RemoteEndPoint}, it's alive"); break; // denotes a pong case 0xB: break; //reserved for further control frames case 0xC: break; case 0xD: break; case 0xE: break; case 0xF: break; default: Console.WriteLine($"Received unknown opcode `{opCode}`. Close connection."); sender.Dispose(); break; } } catch (Exception) { sender.Dispose(); } }