C# 和 JS 中的 WebSocketServers - return 中的乱码

WebSocketServers in C# and JS - Gibberish in return

我用 C# 和 HTML UI 用 JS 做了一个 Websocket 服务器。

我可以让服务器正确地进行通信和握手,但是发送的信息完全是乱码,看起来像这样:

???=u??X?G?

我试过编码,但结果差别不大。

我的 JS 看起来像这样:

    // 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" />

接收信息的 c# 模块如下所示:

        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));

    }

他们都是 return 东西,但是,他们总是 return 这个原始的、乱七八糟的数据,看起来像这样:

???=u??X?G?

我知道它缺少编码,我曾多次尝试对其进行编码 - 但信息看起来更奇怪,实际上从来没有 return 符合我的要求。任何帮助将不胜感激。

更新

调用新连接时调用dataBuffer。

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

Listen() 创建这个:

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

已解决!

昨天又看了一遍,问题解决了。我没有正确解析这些位 - 所以我创建了这个:

    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));

它基于此处的解决方案How to (de)construct data frames in WebSockets hybi 08+?

WebSocket data is framed,所以你必须逐帧读取并从中提取数据。

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

请试试这个

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);
    }
}

已解决!

昨天又看了一遍,问题解决了。我没有正确解析这些位 - 所以我创建了这个:

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));

它基于此处的解决方案How to (de)construct data frames in WebSockets hybi 08+?