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.
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.
Please tell me if there is not enough information in this revision; as it has been modified a few times now.
Thanks in advance.
Client Javascript:
<!DOCTYPE html>  
<meta charset="utf-8" />
<html>
<head>
<script language="javascript" type="text/javascript">
    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("    Reason: " + evt.code );
        writeToScreen("    Reason: " + evt.reason );
        writeToScreen("    Clean: " + evt.wasClean);
    }
    function onMessage(evt)
    {
        writeToScreen("#WebSocket Message Event");
        try
        {
            writeToScreen("<span style=\"color: blue;\">#WebSocket Server Message: " + evt.data+"</span>");
        }
        catch( e )
        {
            writeToScreen(e);
        }
    }
    function onError(evt)
    {
        writeToScreen("<span style=\"color: red;\">#WebSocket Error:</span> " + 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 + "<br>";
            output.appendChild(pre);
        }
        catch( e )
        {
            writeToScreen(e);
        }
    }
    window.addEventListener("load", init, false);
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
The handshake offer I recieve from my client is as follows:
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
I interpret the handshake like so:
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;
        }
    }
}
Send my Header Response:
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");
}
And get the following output from the client ( at this point ):
#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
At this point, if I attempt to execute the following server-side method, the client disconnects like so:
#WebSocket Connection Aborted:
    Reason: 1006
    Reason: 
    Clean: false
Message Code: -Taken from something I found on the net, modified a bit...
public void WriteMessage(byte[] Payload)
{
    byte[] Message;
    int Length = Payload.Length;
    int MaskLength = 4;
    if (Length < 126)
    {
        Message = new byte[2 + MaskLength + Length];
        Message[1] = (byte)Length;
    }
    else if (Length < 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 > 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 > 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 < Message.Length; i++ )
    {
        if (Message[z] == '\0')
        {
            if (Payload.Length > i-z)
                output[i] = (char)Payload[y++];
        }
        else
        {
            output[i] = (char)Message[z++];
        }
    }
    this.OutputWriter.Write(output, 0, output.Length);
    this.OutputWriter.Flush();
}
UPDATE: I just replaced all of the code in this document with my most current.
To summarize:
- 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.
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.
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.
Thank you. -DigitalJedi facepalm
 
     
    