我已经在 python 中编写了自己的 websocket 实现,以自学它们的内部工作原理。我打算通过 websocket 发送大量重复的 JSON 对象,所以我正在尝试实现permessage-deflate
. 压缩在client->server
方向上起作用,但不是在 server -> client
方向上
这是标头交换:
要求
Host: awebsite.com:port
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
Upgrade: websocket
Origin: http://awebsite.com
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Sec-WebSocket-Key: JItmF32mfGXXKYyhcEoW/A==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
回复
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Accept: zYQKJ6gvwlTU/j2xw1Kf0BErg9c=
当我这样做时,我会按预期从客户端获取压缩数据并按预期膨胀。
当我发送未压缩的消息时,我会在客户端得到正常响应,即我发送“你好”并得到“你好”
当我尝试使用这个简单的 python 函数缩小我的消息时:
def deflate(self,data,B64_encode=False):
data=zlib.compress(data)
if B64_encode:
return base64.b64encode(data[2:-4])
else:
return data[2:-4]
我收到一条关于字符不是 utf-8 的错误消息,当我对压缩消息进行 base64 编码时,我只得到了 base64 编码的字符串。我还尝试通过 websocket 将数据作为二进制发送,并在另一端得到一个 blob。我已经在互联网上搜索了一段时间,还没有听说过这种情况。我的猜测是我在错误的步骤压缩数据。下面是我用来发送数据的函数。到目前为止,我一直在将压缩消息输入到send()
函数中,因为从我读过的内容来看,permessage 压缩发生在消息级别,并且所有其他数据保持未压缩。
def send(self, string, TYPE="TEXT"):
import struct
conn = self.conn
datatypes = {
"TEXT": 0x01,
"BINARY": 0x02,
"CLOSE": 0X08,
"PING": 0x09,
"PONG": 0x0A}
b1 = 0x80
b2 = 0
message = ""
if TYPE == "TEXT":
if type(string) == unicode:
b1 |= datatypes["TEXT"]
payload = string.encode("UTF8")
elif type(string) == str:
b1 |= datatypes["TEXT"]
payload = string
message += chr(b1)
else:
b1 |= datatypes[TYPE]
payload = string
message += chr(b1)
length = len(payload)
if length < 126:
b2 |= length
message += chr(b2)
elif length < (2 ** 16) - 1:
b2 |= 126
message += chr(b2)
l = struct.pack(">H", length)
message += l
else:
l = struct.pack(">Q", length)
b2 |= 127
message += chr(b2)
message += l
message += payload
try:
conn.send(str(message))
except socket.error:
traceback.print_exc()
conn.close()
if TYPE == "CLOSE":
self.Die = True
conn.shutdown(2)
conn.close()
print self.myid,"Closed"