我已经在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=当我这样做时,我从客户端得到预期的压缩数据,它会按预期膨胀。
当我发送一条未压缩的消息时,我在客户端得到一个正常的响应(我发送"hello“和"hello”)。
当我试图使用这个简单的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()函数中,因为根据我所读到的,每条消息的压缩都发生在消息级别上,而所有其他数据都是未压缩的。
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"发布于 2021-04-08 04:15:22
经过多次调查,我发现我的问题是"RTFM“。在(a?) 马努阿人l on perMessage压缩的第三段中,它说
WebSocket客户端可能在WebSocket期间提供多个PMCEs。 开始握手。接收到这些报价的对等WebSocket服务器可以选择和接受首选的服务,也可以拒绝所有这些服务。PMCEs使用 RSV1帧头的WebSocket位,以指示 消息是否被压缩,因此端点可以选择不对 用不可压缩的内容压缩消息。
当我第一次设置它时,我不知道rsv位做了什么,默认情况下将它们设置为0。我的代码现在允许在我的程序中的send()函数中设置压缩。它很好地将我的消息从30200字节缩减到149个字节。
我修改的代码现在如下所示:
def deflate2(self,data):
data=zlib.compress(data)
data=data[2:-4]
return data
def send(self, string, TYPE="TEXT",deflate=False):
import struct
if (deflate):
string=self.deflate(string)
conn = self.conn
datatypes = {
"TEXT": 0x01,
"BINARY": 0x02,
"CLOSE": 0X08,
"PING": 0x09,
"PONG": 0x0A}
b1 = 0x80 #0b100000000
if(deflate): b1=0xC0 #0b110000000 sets RSV1 to 1 for compression
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:
if self.debug:
for x in message: print("S>: ",x,hex(ord(x)),ord(x))
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"https://stackoverflow.com/questions/66972354
复制相似问题