After the fight, all morning I got a handshake, but now I'm actually stuck sending and receiving messages. I searched for answers to no avail, so I thought that I was finally activating here and asking: /
My client is still very simple:
function testWebSocket() { if (!window.WebSocket) { alert('WebSockets are NOT supported by your browser.'); return; } try { var ws = new WebSocket('ws://localhost:8181/websession'); ws.onopen = function () { alert('Handshake successfully established. Ready for data...'); }; ws.onmessage = function (e) { alert('Got WebSockets message: ' + e.data); } ws.onclose = function () { alert('Connection closed.'); }; } catch (e) { alert(e); } }
yes, I made a lot of borrowing code for this ... I'm just trying to get a proof of concept working with a simple "chat application"
my server consists mainly of two classes: SocketServer.cs and SocketClient.cs
follow:
SocketServer.cs
using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.Net; using System.IO; namespace WebSocketServer.Entities { class SocketServer { public static Form1 parentForm; TcpListener socketServer; public static List<SocketClient> ClientList = new List<SocketClient>(); public SocketServer(Form1 pForm) { parentForm = pForm; parentForm.ApplyText("Socket Class Initiated\r\n"); socketServer = new TcpListener(IPAddress.Any, 8181);
Socketclient.cs
using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.IO; using System.Threading; using System.Security.Cryptography; namespace WebSocketServer.Entities { class SocketClient { public TcpClient Client; StreamReader reader; StreamWriter writer; Form1 parentForm; public SocketClient(TcpClient client, Form1 pForm) { parentForm = pForm; Client = client; Thread clientThread = new Thread(new ThreadStart(StartClient)); clientThread.Start(); } private void StartClient() { SocketServer.ClientList.Add(this); // create a reader for this client reader = new StreamReader(Client.GetStream()); // create a writer for this client writer = new StreamWriter(Client.GetStream()); var headers = new Dictionary<string, string>(); string line = ""; while ((line = reader.ReadLine()) != string.Empty) { if (!string.IsNullOrEmpty(line)) { var tokens = line.Split(new char[] { ':' }, 2); if (!string.IsNullOrWhiteSpace(line) && tokens.Length > 1) { headers[tokens[0]] = tokens[1].Trim(); } } } String secWebSocketAccept = ComputeWebSocketHandshakeSecurityHash09(headers["Sec-WebSocket-Key"]); // send handshake to this client only writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake"); writer.WriteLine("Upgrade: WebSocket"); writer.WriteLine("Connection: Upgrade"); writer.WriteLine("WebSocket-Origin: http://localhost:63422/"); writer.WriteLine("WebSocket-Location: ws://localhost:8181/websession"); writer.WriteLine("Sec-WebSocket-Accept: " + secWebSocketAccept); writer.WriteLine(""); writer.Flush(); SocketServer.SendBroadcast("New Client Connected"); Thread clientRun = new Thread(new ThreadStart(RunClient)); clientRun.Start(); } public static String ComputeWebSocketHandshakeSecurityHash09(String secWebSocketKey) { const String MagicKEY = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; String secWebSocketAccept = String.Empty; // 1. Combine the request Sec-WebSocket-Key with magic key. String ret = secWebSocketKey + MagicKEY; // 2. Compute the SHA1 hash SHA1 sha = new SHA1CryptoServiceProvider(); byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret)); // 3. Base64 encode the hash secWebSocketAccept = Convert.ToBase64String(sha1Hash); return secWebSocketAccept; } private void RunClient() { try { string line = ""; while (true) { line = reader.ReadLine(); if (!string.IsNullOrEmpty(line)) { parentForm.ApplyText(line + "\r\n"); SocketServer.SendBroadcast(line); } } } catch { parentForm.ApplyText("Client Disconnected\r\n"); SocketServer.CloseClient(this); } } public void Dispose() { System.GC.SuppressFinalize(this); } } }
I can connect to multiple instances in Chrome, and all connected clients are displayed on my server, and I see a warning that the handshake was successful. But when I try to send text from the client (the code is not shown above, but this is a pretty simple thing ws.send (text)), it gets to the server as garbled text. When I try to make writer.WriteLine ("whatever") from server to client, the onmessage event never fires. I did a lot of review after I finally got a handshake, sorted it out and did not find good examples of how to resolve this.
Should I not use StreamWriter? I missed something else in my handshake (maybe a protocol).
TIA for search and assistance.
Edit:
The code below works, but I donβt know how to change it to allow the length of the text in a dynamic format. I'm fine, just being able to send text that is 127 or less at the moment, but I can't figure out how to get even 4.
public static void SendBroadcast(string text) { StreamWriter writer; // loop through the array and send text to all clients foreach (SocketClient client in ClientList) { if (client.Client.Connected) { try { NetworkStream l_Stream = client.Client.GetStream(); List<byte> lb = new List<byte>(); lb.Add(0x81); lb.Add(0x04); lb.AddRange(Encoding.UTF8.GetBytes("test")); l_Stream.Write(lb.ToArray(), 0, 6); } catch { CloseClient(client); } } } }
I tried changing lb.Add (0x04) to lb.Add (0x07) and send "testing" without cubes. I am also confused by the fact that the parameters are l_Stream.Write (). I know this is an array of bytes, offset and size, but the size of what?