0

Ive made a Websocket server in C# and a HTML UI together with JS.

I can get the server to communicate and do the handshake properly, but the information being sent is absolute gibberish and looks something like this:

???=u??X?G?

I have tried encoding it, but the result is not very different.

My JS looks like this:

    // the user clicked the big red button
    $('#bigredbutton_send').click(function () {
        ws_send($('#console_input').val());
    });

    $('#console_input').keyup(function (e) {
        if(e.keyCode == 13) // enter is pressed
            ws_send($('#console_input').val());
    });

CSS:

    <input type="image" src="button.png"  name="bigredbutton_send" id="bigredbutton_send" value="VALUE" /> 
    <input type="text" name="console_input" id="console_input" value="Hello123" />

and c# module that recieves the information looks like this:

        private void Read(IAsyncResult ar)
    {

        int sizeOfReceivedData = ConnectionSocket.EndReceive(ar);
        if (sizeOfReceivedData > 0)
        {
            int start = 0, end = dataBuffer.Length - 1;

            // if we are not already reading something, look for the start byte as specified in the protocol
            if (!readingData)
            {
                for (start = 0; start < dataBuffer.Length - 1; start++)
                {
                    if (dataBuffer[start] == (byte)WrapperBytes.Start)
                    {
                        readingData = true; // we found the begining and can now start reading
                        start++; // we dont need the start byte. Incrementing the start counter will walk us past it
                        break;
                    }
                }
            } // no else here, the value of readingData might have changed

            // if a begining was found in the buffer, or if we are continuing from another buffer
            if (readingData)
            {
                bool endIsInThisBuffer = false;
                // look for the end byte in the received data
                for (end = start; end < sizeOfReceivedData; end++)
                {
                    byte currentByte = dataBuffer[end];
                    if (dataBuffer[end] == (byte)WrapperBytes.End)
                    {
                        endIsInThisBuffer = true; // we found the ending byte
                        break;
                    }
                }

                // the end is in this buffer, which means that we are done reading
                if (endIsInThisBuffer == true)
                {
                    // we are no longer reading data
                    readingData = false;
                    // put the data into the string builder
                    dataString.Append(Encoding.UTF8.GetString(dataBuffer, start, end - start));
                    // trigger the event
                    int size = Encoding.UTF8.GetBytes(dataString.ToString().ToCharArray()).Length;

                    recievedData = dataString.ToString();

                    OnDataReceived(new DataReceivedEventArgs(size, dataString.ToString()));
                    dataString = null;
                    dataString = new StringBuilder();


                }
                else // if the end is not in this buffer then put everyting from start to the end of the buffer into the datastring and keep on reading
                {
                    dataString.Append(Encoding.UTF8.GetString(dataBuffer, start, end - start));
                }
            }

            // continue listening for more data
            Listen();
        }
        else // the socket is closed
        {
            if (Disconnected != null)
                Disconnected(this, EventArgs.Empty);
        }


        // Testing to see if readable
        ReadRecievedData(Convert.ToString(dataString));

    }

And they all return something, however, they always return this raw, gibberishlike, data that looks like this:

???=u??X?G?

I understand that it lacks encoding, and I have tried to encode it several times - but the information just looks weirder and actually never returns anything of what I want it to. Any help would be greatly appreciated.

Update

The dataBuffer is called when a new connection is invoked.

        public WebSocketConnection(Socket socket, int bufferSize)
    {
        ConnectionSocket = socket;
        dataBuffer = new byte[bufferSize];
        dataString = new StringBuilder();
        GUID = System.Guid.NewGuid();
        Listen();
    }

Listen() creates this:

        private void Listen()
    {
        ConnectionSocket.BeginReceive(dataBuffer, 0, dataBuffer.Length, 0, Read, null);
    }

SOLVED!

I looked over it again yesterday and I solved the problem. I wasnt parsing the bits correct - So I created this instead:

    byte b = dataBuffer[1];
    int dataLength = 0;
    int totalLength = 0;
    int keyIndex = 0;
    int length = dataBuffer.Length;

    if (b - 128 <= 125)
    {
        dataLength = b - 128;
        keyIndex = 2;
        totalLength = dataLength + 6;
    }

    if (b - 128 == 126)
    {
        dataLength = BitConverter.ToInt16(new byte[] { dataBuffer[3], dataBuffer[2] }, 0);
        keyIndex = 4;
        totalLength = dataLength + 8;
    }

    if (b - 128 == 127)
    {
        dataLength = (int)BitConverter.ToInt64(new byte[] { dataBuffer[9], dataBuffer[8], dataBuffer[7], dataBuffer[6], dataBuffer[5], dataBuffer[4], 
            dataBuffer[3], dataBuffer[2] }, 0);
        keyIndex = 10;
        totalLength = dataLength + 14;
    }

    if (totalLength > length)
        throw new Exception("The buffer length is small than the data length");

    byte[] key = new byte[] { dataBuffer[keyIndex], dataBuffer[keyIndex + 1], dataBuffer[keyIndex + 2], dataBuffer[keyIndex + 3] };

    int dataIndex = keyIndex + 4;
    int count = 0;
    for (int i = dataIndex; i < totalLength; i++)
    {
        dataBuffer[i] = (byte)(dataBuffer[i] ^ key[count % 4]);
        count++;
    }

    ReadRecievedData(Encoding.ASCII.GetString(dataBuffer, dataIndex, dataLength));

It builds on the solution over hereHow to (de)construct data frames in WebSockets hybi 08+?

Community
  • 1
  • 1
Paul
  • 478
  • 2
  • 16
  • 1
    Where is defined and filled `dataBuffer` ? – Mike Jan 05 '15 at 10:44
  • Ill edit it in, Mike. One second. – Paul Jan 05 '15 at 10:45
  • 1
    The gibberish string that you have mentioned in your question is recieved with one chunk of data or more? – Mike Jan 05 '15 at 11:04
  • Whenever an event is triggered (such as the button click) - You recieve a little bit more each time. After 5-6 clicks the information looks mroe like this: `????;F??W*?? u?? ,??AI??f???????tk?? 5???F>?#[?O)??????????????????????????????????` – Paul Jan 05 '15 at 11:08
  • 1
    Does your OnDataReceived trigger every time you click the button? – Mike Jan 05 '15 at 11:13
  • Actually no, it almost never triggers - Thats code I dont use any more. Its the ReadRecievedData that almost always trigger. – Paul Jan 05 '15 at 11:21
  • 1
    That means that your received data does not contain end byte and bytes may not be eligable for converting to string – Mike Jan 05 '15 at 11:26
  • Okay - What would have to be changed? The methods sending the data or am I loosing something a long the way? – Paul Jan 05 '15 at 11:29
  • Does your WrapperBytes.End = 255 ? – Mike Jan 05 '15 at 11:50

3 Answers3

1

WebSocket data is framed, so you have to read frame by frame and extract the data from it.

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

Writing a WebSocket server in C#

Writing WebSocket servers

vtortola
  • 34,709
  • 29
  • 161
  • 263
  • Thank you vtortola - I am trying to read this payload data - The problem is jsut that together with the standard RFC 6455 and my knowledge of the ethernet mask, I am failing horribly. – Paul Jan 05 '15 at 12:43
  • 1
    Well you have to read the data in binary like `Byte[]`, then check for the bits that give you the length and all that. It is a little bit cumbersome if you have never do it before. You do not need to worry about the ethernet. On the connection, you will only get websocket data. So basically, you must start reading from the socket , find out the total length of the frame and then read till there, find out the length of the payload, unmask it and that is :) – vtortola Jan 05 '15 at 13:58
  • 1
    I developed a [WebSocket server component in C#](http://vtortola.github.io/WebSocketListener/), if may be worth for you to take a look. – vtortola Jan 05 '15 at 13:59
  • Thanks Vtortola. Maybe Il just do that instead. – Paul Jan 05 '15 at 14:56
  • Again, Thanks for all your help vtortola - I solved it and provided the solution above. Your chart showed me what to do and how to deal with the framing. – Paul Jan 26 '15 at 15:33
1

Please try this

private void Read(IAsyncResult ar)
{

    int sizeOfReceivedData = ConnectionSocket.EndReceive(ar);
    if (sizeOfReceivedData > 0)
    {
        int start = 0, end = sizeOfReceivedData - 1;

        var bufferList = dataBuffer.ToList();

        bool endIsInThisBuffer = dataBuffer.Contains(255); // 255 = end
        if (endIsInThisBuffer)
        {
            end = bufferList.IndexOf(255);
            end--; // we dont want to include this byte
        }

        bool startIsInThisBuffer = dataBuffer.Contains(0); // 0 = start
        if (startIsInThisBuffer)
        {
            var zeroPos = bufferList.IndexOf(0);
            if (zeroPos < end) // we might be looking at one of the bytes in the end of the array that hasn't been set
            {
                start = zeroPos;
                start++; // we dont want to include this byte
            }
        }

        dataString.Append(Encoding.UTF8.GetString(dataBuffer, start, (end - start) + 1));

        if (endIsInThisBuffer)
        {
            var data = dataString.ToString();
            OnDataReceived(new DataReceivedEventArgs(data.Length, data));

            // Testing to see if readable
            ReadRecievedData(data);

            dataString = new StringBuilder();
        }

        Listen();
    }
    else // the socket is closed
    {
        if (Disconnected != null)
            Disconnected(this, EventArgs.Empty);
    }
}
Mike
  • 3,766
  • 3
  • 18
  • 32
  • Wow Mike, thanks a billion. Your code runs, and it runs a lot more smoothly than mine does, but the response I receive is just like my previous: `???!l` – Paul Jan 05 '15 at 12:40
0

SOLVED!

I looked over it again yesterday and I solved the problem. I wasnt parsing the bits correct - So I created this instead:

byte b = dataBuffer[1];
int dataLength = 0;
int totalLength = 0;
int keyIndex = 0;
int length = dataBuffer.Length;

if (b - 128 <= 125)
{
    dataLength = b - 128;
    keyIndex = 2;
    totalLength = dataLength + 6;
}

if (b - 128 == 126)
{
    dataLength = BitConverter.ToInt16(new byte[] { dataBuffer[3], dataBuffer[2] }, 0);
    keyIndex = 4;
    totalLength = dataLength + 8;
}

if (b - 128 == 127)
{
    dataLength = (int)BitConverter.ToInt64(new byte[] { dataBuffer[9], dataBuffer[8], dataBuffer[7], dataBuffer[6], dataBuffer[5], dataBuffer[4], 
        dataBuffer[3], dataBuffer[2] }, 0);
    keyIndex = 10;
    totalLength = dataLength + 14;
}

if (totalLength > length)
    throw new Exception("The buffer length is small than the data length");

byte[] key = new byte[] { dataBuffer[keyIndex], dataBuffer[keyIndex + 1], dataBuffer[keyIndex + 2], dataBuffer[keyIndex + 3] };

int dataIndex = keyIndex + 4;
int count = 0;
for (int i = dataIndex; i < totalLength; i++)
{
    dataBuffer[i] = (byte)(dataBuffer[i] ^ key[count % 4]);
    count++;
}

ReadRecievedData(Encoding.ASCII.GetString(dataBuffer, dataIndex, dataLength));

It builds on the solution over hereHow to (de)construct data frames in WebSockets hybi 08+?

Paul
  • 478
  • 2
  • 16