Note that there are some explanatory texts on larger screens.

plurals
  1. POWebSocket Connection Drops before onmessage
    text
    copied!<p>I've written a WebSocket client in Javascript that connects and shakes hands with C# my server. Currently, upon 'Flushing' my output stream ( only after I have sent the header BACK to the client and affirmed my connection ), the client crashes and generates a server-side exception when I try to write the next time around. The latter behavior is expected, however what I can't figure out is why the flush would drop the connection. I'm using a TcpListener and a Socket with a StreamWriter on the server end, and a plain WebSocket on the client. </p> <p>What is truly perplexing about this scenario is that during transmission of the 'handshake', text can be transmitted both ways and a Flush is executed after each line is sent, but as soon as the handshake is complete, a flush terminates the connection.</p> <p>Please tell me if there is not enough information in this revision; as it has been modified a few times now.</p> <p>Thanks in advance.</p> <p>Client Javascript:</p> <pre><code>&lt;!DOCTYPE html&gt; &lt;meta charset="utf-8" /&gt; &lt;html&gt; &lt;head&gt; &lt;script language="javascript" type="text/javascript"&gt; var wsUri = "ws://127.0.0.1:9002/cc"; var output; var websocket = null; function init() { StartWebSocket(); } function StartWebSocket() { output = document.getElementById("output"); writeToScreen("#WebSocket Starting"); websocket = new WebSocket(wsUri,"lorem.ipsum.com"); writeToScreen("#WebSocket Instantiated"); websocket.removeEventListener("open",onOpen,false); websocket.addEventListener("open",onOpen,false); websocket.removeEventListener("close",onClose,false); websocket.addEventListener("close",onClose,false); websocket.removeEventListener("message",onMessage,false); websocket.addEventListener("message",onMessage,false); websocket.removeEventListener("error",onError,false); websocket.addEventListener("error",onError,false); writeToScreen("#WebSocket Events Attached"); } function onOpen(evt) { try { writeToScreen("#WebSocket Connection Established"); writeToScreen("#WebSocket BinaryType: " + websocket.binaryType); writeToScreen("#WebSocket Protocol: " + websocket.protocol); writeToScreen("#WebSocket Extensions: " + websocket.extensions); doSend("TestOutput\r\n\r"); } catch( e ) { writeToScreen(e); } } function onClose(evt) { writeToScreen("#WebSocket Connection Aborted:"); writeToScreen("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Reason: " + evt.code ); writeToScreen("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Reason: " + evt.reason ); writeToScreen("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Clean: " + evt.wasClean); } function onMessage(evt) { writeToScreen("#WebSocket Message Event"); try { writeToScreen("&lt;span style=\"color: blue;\"&gt;#WebSocket Server Message: " + evt.data+"&lt;/span&gt;"); } catch( e ) { writeToScreen(e); } } function onError(evt) { writeToScreen("&lt;span style=\"color: red;\"&gt;#WebSocket Error:&lt;/span&gt; " + evt.data); } function doSend(message) { try { websocket.send(message); writeToScreen("#WebSocket Output Written to Server: " + message); } catch( e ) { writeToScreen(e); } } function writeToScreen(message) { try { var pre = document.createElement("a"); pre.style.wordWrap = "break-word"; pre.innerHTML = message + "&lt;br&gt;"; output.appendChild(pre); } catch( e ) { writeToScreen(e); } } window.addEventListener("load", init, false); &lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;div id="output"&gt;&lt;/div&gt; &lt;/body&gt; &lt;/html&gt; </code></pre> <p>The handshake offer I recieve from my client is as follows:</p> <pre><code>GET /cc HTTP/1.1 Upgrade: websocket Connection: Upgrade Host: 127.0.0.1:9002 Origin: http://localhost Sec-WebSocket-Key: icajBpkAfgA+YbVheBpDsQ== Sec-WebSocket-Version: 13 </code></pre> <p>I interpret the handshake like so:</p> <pre><code>public override void Interpret(string Argument) { if (String.IsNullOrEmpty(Argument)) { return; } else { if( !HeaderFinished ) { if (!HeaderStarted) { if (Argument.StartsWith("GET /")) { this.Role = "client"; HeaderStarted = true; this.Server.Print("Connection at " + this.Address + " set to client."); } else { return; } } else { if (Argument.StartsWith("Sec-WebSocket-Key:")) { this.Key = Argument.Split(' ')[1].TrimEnd().TrimStart(); return; } else if (Argument.StartsWith("Sec-WebSocket-Version:")) { this.HeaderFinished = true; this.WriteHeaderResponse(); HeaderSent = true; return; } } } else { this.InterpretMessage(DecodeMessage(Argument)); return; } } } </code></pre> <p>Send my Header Response:</p> <pre><code>public void WriteHeaderResponse() { this.WriteLine("HTTP/1.1 101 Switching Protocols"); this.WriteLine("Upgrade: websocket"); this.WriteLine("Connection: Upgrade"); String NewKey = ComputeResponseKey(this.Key); this.WriteLine("Sec-WebSocket-Accept: " + NewKey); this.WriteLine("Sec-WebSocket-Protocol: lorem.ipsum.com"); this.WriteLine("\r\n"); } </code></pre> <p>And get the following output from the client ( at this point ):</p> <pre><code>#WebSocket Starting #WebSocket Instantiated #WebSocket Events Attached #WebSocket Connection Established #WebSocket BinaryType: blob #WebSocket Protocol: lorem.ipsum.com #WebSocket Extensions: #WebSocket Output Written to Server: TestOutput </code></pre> <p>At this point, if I attempt to execute the following server-side method, the client disconnects like so:</p> <pre><code>#WebSocket Connection Aborted: Reason: 1006 Reason: Clean: false </code></pre> <p>Message Code: -Taken from something I found on the net, modified a bit...</p> <pre><code>public void WriteMessage(byte[] Payload) { byte[] Message; int Length = Payload.Length; int MaskLength = 4; if (Length &lt; 126) { Message = new byte[2 + MaskLength + Length]; Message[1] = (byte)Length; } else if (Length &lt; 65536) { Message = new byte[4 + MaskLength + Length]; Message[1] = (byte)126; Message[2] = (byte)(Length / 256); Message[3] = (byte)(Length % 256); } else { Message = new byte[10 + MaskLength + Length]; Message[1] = (byte)127; int left = Length; int unit = 256; for (int i = 9; i &gt; 1; i--) { Message[i] = (byte)(left % unit); left = left / unit; if (left == 0) break; } } //Set FIN Message[0] = (byte)129;// (0 | 0x80); //Set mask bit //Message[1] = (byte)(Message[1] | 0x80); //GenerateMask(Message, Message.Length - MaskLength - Length); //if (Length &gt; 0) //MaskData(Payload, 0, Length, Message, Message.Length - Length, Message, Message.Length - MaskLength - Length); char[] output = new char[Message.Length-4]; for( int i = 0, y = 0, z = 0; i &lt; Message.Length; i++ ) { if (Message[z] == '\0') { if (Payload.Length &gt; i-z) output[i] = (char)Payload[y++]; } else { output[i] = (char)Message[z++]; } } this.OutputWriter.Write(output, 0, output.Length); this.OutputWriter.Flush(); } </code></pre> <p>UPDATE: I just replaced all of the code in this document with my most current.</p> <p>To summarize:</p> <pre><code>- The client-server handshake has been matched on both sides. - A path has been defined in the URI for the WebSocket. - Data packets are now being 'properly' framed. </code></pre> <p>One point I have only noticed while editing this, is the last few lines of my WriteMessage method. After doing all of my framing, I convert my byte array to a character array and use a StreamReader.Write to send it. I'm not sure if this is a viable solution or not, so please put me in check if it's not.</p> <p>Otherwise I am baffled. This seems to comply to all of the standards that I have read anything about, but still fails me miserably. This is quite the deal-maker if I can get it working, so I really do appreciate anyone's help.</p> <p>Thank you. -DigitalJedi <em>facepalm</em></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload