如何(de)在WebSockets hybi 08+中构建数据框架?

时间:2011-08-12 12:30:13

标签: c# websocket

自Chrome更新至第14版后,它们从version three of the draft转到version eight of the draft

我有一个在WebSocket上运行的内部聊天应用程序,虽然我已经让新的握手正常工作,但数据框架显然也发生了变化。我的WebSocket服务器基于Nugget

是否有人使用WebSocket处理草案的第8版,并举例说明如何通过网络发送数据?

3 个答案:

答案 0 :(得分:17)

(另见:How can I send and receive WebSocket messages on the server side?


这很容易,但了解格式很重要。

第一个字节几乎总是1000 0001,其中1表示“最后一帧”,三个0是保留位,到目前为止没有任何意义,{{1} }表示它是一个文本框架(Chrome使用0001方法发送)。

更新> Chrome现在还可以发送带有ws.send()的二进制帧。第一个字节的后四位将是ArrayBuffer,因此您可以在文本之间进行区分和二进制数据。数据的解码工作方式完全相同。)

第二个字节包含0002(意味着它被“屏蔽”(编码)),后面跟着表示帧大小的7位。如果它在1000 0000之间,那就是大小。如果它是111 1101,则以下2个字节是长度(因为它不适合7位),如果它是111 1110,则后面的8个字节是长度(如果它不适合用两个字节)。

之后是四个字节,它们是解码帧数据所需的“掩码”。这是使用xor编码完成的,xor编码使用由111 1111数据定义的掩码之一。解码就像indexOfByteInData mod 4一样(encodedByte xor maskBytemaskByte)。

现在我必须说我对C#没有经验,但这是一些伪代码(我担心会有一些JavaScript口音):

indexOfByteInData mod 4

您也可以下载the specification这可能会有所帮助(当然,它包含了解格式所需的一切)。

答案 1 :(得分:11)

这个c#代码对我来说很好。通过套接字将浏览器中的文本数据解码到c#服务器。

    public static string GetDecodedData(byte[] buffer, int length)
    {
        byte b = buffer[1];
        int dataLength = 0;
        int totalLength = 0;
        int keyIndex = 0;

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

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

        if (b - 128 == 127)
        {
            dataLength = (int)BitConverter.ToInt64(new byte[] { buffer[9], buffer[8], buffer[7], buffer[6], buffer[5], buffer[4], buffer[3], buffer[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[] { buffer[keyIndex], buffer[keyIndex + 1], buffer[keyIndex + 2], buffer[keyIndex + 3] };

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

        return Encoding.ASCII.GetString(buffer, dataIndex, dataLength);
    }

答案 2 :(得分:2)

为了更准确,Chrome已从协议的Hixie-76版本变为协议的HyBi-10版本。 HyBi-08到HyBi-10都报告为版本8,因为它实际上只是规范文本发生了变化,而不是电线格式。

框架已从使用'\ x00 ... \ xff'变为使用2-7字节标头,每个框架包含有效负载的长度等。在规范的section 4.2中有一个帧格式图。另请注意,从客户端(浏览器)到服务器的数据被屏蔽(客户端 - 服务器帧头的4个字节包含取消屏蔽密钥)。

您可以查看websockify这是我为支持noVNC而创建的TCP套接字代理/网桥的WebSockets。它是在python中实现的,但您应该能够从encode_hybidecode_hybi例程中获得想法。