无法解码来自客户端的握手请求

Posted

技术标签:

【中文标题】无法解码来自客户端的握手请求【英文标题】:Can't decode handshake request from client 【发布时间】:2021-11-09 00:37:01 【问题描述】:

我正在尝试将 python3 套接字与 javascript WebSocket 连接。我正在 localhost:8080 上测试服务器代码,并与 Chrome(94.0) 连接。

WebSocket 客户端和套接字服务器 建立连接。但是,如果服务器不遵循协议并响应握手,则连接将被关闭。根据协议,客户端 WebSocket 向套接字服务器发送一个 utf-8 编码的 GET 请求,服务器必须解析该请求才能完成握手。

我从客户那里得到的是这样的:

\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03\x97t\xb1\xf7\xac\x99\x91\xd4\xf5\n\xdf\xc3X\x8af<\xbe\x99(0\x88\x9a!\xc6\xc9\x17]\xfe\xd9sP\xcc \xa8\xcf\x90\x8a\xfcm\xbcj-5\xdf\xf90\x81\xc8Y\xc1\x85q"\xfe!C\xbb\t\xbd\xe0\x8d\xf1\xe5\x00 \x1a\x1a\x13\x01\x13\x02\x13\x03\xc0+\xc0/\xc0,\xc00\xcc\xa9\xcc\xa8\xc0\x13\xc0\x14\x00\x9c\x00\x9d\x00/\x005\x01\x00\x01\x93\x1a\x1a\x00\x00\x00\x17\x00\x00\xff\x01\x00\x01\x00\x00\n\x00\n\x00\x08\xfa\xfa\x00\x1d\x00\x17\x00\x18\x00\x0b\x00\x02\x01\x00\x00#\x00\x00\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\r\x00\x12\x00\x10\x04\x03\x08\x04\x04\x01\x05\x03\x08\x05\x05\x01\x08\x06\x06\x01\x00\x12\x00\x00\x003\x00+\x00)\xfa\xfa\x00\x01\x00\x00\x1d\x00 \xfa)\xd5\x85<\x81.\x7f\xc0\x87wA!\xf1\xc9\xf80\xeb\x01\xdc\xed3m\xd1\x98\xd6\xd8\xd7\x7f#\rM\x00-\x00\x02\x01\x01\x00+\x00\x0b\n\x8a\x8a\x03\x04\x03\x03\x03\x02\x03\x01\x00\x1b\x00\x03\x02\x00\x02JJ\x00\x01\x00\x00\x15\x00\xf7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00

客户端始终发送这些字节,尽管这看起来不像是合法的 GET 请求。这不能被 utf-8 或其他编码(包括 utf-16-le、utf-16-be、unicode-escape 等)解码。

客户来源:

var client = new WebSocket('wss://127.0.0.1:8080')

client.onopen = function(e) 
    console.log("open");


client.onmessage = function(e) 
    console.log(e.data)

服务器握手处理程序:

def handshake(client, address):
    req = client.recv(1024).decode('utf-8')
    key = (re.search('Sec-WebSocket-Key:\s+(.*?)[\n\r]+', req).groups()[0].strip())
    response_key = b64encode(sha1(key + sockey).digest())
    response = '\r\n'.join(websock_ans).format(key=response_key)
    client.send(response.encode('utf-8'))

由于客户端请求不是 utf-8 字节,因此在第 2 行会出现解码错误。

遵循websocket协议(https://datatracker.ietf.org/doc/html/rfc6455),sockey和websock_ans定义如下:

sockey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
websock_ans = 
    'HTTP/1.1 101 Switching Protocols',
    'Upgrade: websocket',
    'Connection: Upgrade',
    'Sec-WebSocket-Accept: key\r\n\r\n',

WebSocket 是否压缩/加密其 GET 请求?据我检查,文档没有说明任何压缩/加密算法。

提前致谢。

【问题讨论】:

既然不是UTF-8,那你为什么不把.decode('utf-8')去掉,看看是什么字节? 你是对的 - 这是原始代码。我从客户端收到的字节在第一个 sn-p 中提到,以 \x16\x03\x01\... 【参考方案1】:

使用 gzip 将字节转换为对象。

【讨论】:

我试图找到它的参考资料,但找不到 WebSockets 的参考资料。 websocket 是否压缩,如果是,它使用什么参数?

以上是关于无法解码来自客户端的握手请求的主要内容,如果未能解决你的问题,请参考以下文章

来自服务器端的 WebSockets 握手回复,草稿 00

三次握手和四次挥手

TCP面试题

SSL 握手后,客户端的会话密钥存储在哪里?

三次握手四次挥手

TCP-三次握手四次挥手