Python中的WebSocket帧解码

Posted

技术标签:

【中文标题】Python中的WebSocket帧解码【英文标题】:WebSocket frame decoding in Python 【发布时间】:2013-04-01 08:31:36 【问题描述】:

我尝试在服务器端实现 WebSocket 帧取消屏蔽算法(基于此:How can I send and receive WebSocket messages on the server side?)。这是我得到的:

def decode(data):
    frame = bytearray(data)

    length = frame[1] & 127

    indexFirstMask = 2
    if length == 126:
        indexFirstMask = 4
    elif length == 127:
        indexFirstMask = 10

    indexFirstDataByte = indexFirstMask + 4
    mask = frame[indexFirstMask:indexFirstDataByte]

    i = indexFirstDataByte
    j = 0
    decoded = []
    while i < len(frame):
        decoded.append(frame[i] ^ mask[j%4])
        i += 1
        j += 1

    print decoded

    return "".join(chr(byte) for byte in decoded)

但是我得到了非常奇怪的结果。在 javascript 方面:

w = new WebSocket("ws://localhost:2000");
w.send("test");
w.send("test");
w.send("test");
w.send("test");

在服务器端生成:

[42, 73, 45, 46, 1, 0]
[42, 1, 98, 0, 0]
[2, 97, 0, 0]
[2, 97, 0, 0]

更多对w.send("test"); 的调用会产生[2, 97, 0, 0]。前两个数组的长度也大于 4(单词test 中的字符数)。这些都没有转换为单词test。看来我的解码代码一定做错了什么。是什么原因造成的?有什么帮助吗?

编辑看看原始帧:

[193, 134, 48, 166, 232, 11, 26, 239, 197, 37, 49, 166]
[193, 133, 57, 161, 169, 218, 19, 160, 203, 218, 57]
[193, 132, 150, 97, 124, 54, 148, 0, 124, 54]
[193, 132, 163, 26, 102, 249, 161, 123, 102, 249]
[193, 132, 238, 212, 210, 156, 236, 181, 210, 156]

当然,这些数字有点随机(由于屏蔽),但请注意,第二个字节(应该表示有效负载的长度)是134,然后是133,然后总是132。前两帧也比其他帧长。这是怎么回事?

【问题讨论】:

请看一下这个答案,它可能对你有帮助***.com/a/9778823/1193863 【参考方案1】:

我又看了一遍这个帧,我意识到第一个字节:

193[DEC] == 11000001[BIN]

根据规范意味着使用RSV1(第二位是1)。这似乎意味着使用了扩展名,实际上在我的握手代码中我发现了以下行:

ext = req.headers.get("Sec-WebSocket-Extensions", "").strip()
if ext:
    res += "Sec-WebSocket-Extensions: %s\r\n" % ext

在 Chrome 中我可以看到:

Sec-WebSocket-Extensions:x-webkit-deflate-frame

当我握手时。

我还不确定这些扩展是如何工作的,但是从握手代码中删除这 3 行可以解决问题。

【讨论】:

以上是关于Python中的WebSocket帧解码的主要内容,如果未能解决你的问题,请参考以下文章

WebSocket帧数据 解码/转码

Go语言实现WebSocket协议

从 Python 中的 WebSocket 读取(来自 Javascript WebSocket 的数据)

微信小程序: WebSocket应用

从 websocket 中的客户端接收到的解码缓冲区

Websocket 在 localhost 但不是 Heroku