websocket如何解决tcp多请求自动合并成一条请求的问题
这几天又遇到了个头大的问题 —— tcp会将几个连续发送出去的请求合并成一个请求发出去,也就是说,并不是在客户端send几次,server端就接收几次,有可能客户端连续改送5个请求,但在server端5个请求却是合并成一个,只recv一次的。
如果是普通的socket编程,拆解几次请求应该还比较好做,因为改送和接收的消息都是明文,自己给发送的数据加个特殊的结束符就好了,接收时,根据结束符split一下,就可以将多个请求拆解开了。但websocket发送和接收的并不是明文,还会特别加上一些东西。而当下safari支持还是76协议,chrome已经在支持draft10了,拆解又需要分两种情况分别对待了。
76协议还好办,因为加的字符很简单,所有的消息都会在前面加\x00,后面加\xff。所以拆解也比较容易,但draft-10就很麻烦了。
封装了一下相关的代码:
def __parseRequire(self,data):
dataList = []
if self.__getDraftType() == "76":
dataList = data[1:-1].split("\xFF\x00")
elif self.__getDraftType() == "10":
if data[0] != "\x81": return
end = False
while True:
length = int(binascii.b2a_hex(data[1]),16) & 0x7f
if length < 126:
mask = data[2:6]
text = data[6:6+length]
if 6+length == len(data):
end = True
else:
data = data[6+length:]
elif length == 126:
length = struct.unpack("!H", data[2:4])[0]
mask = data[4:8]
text = data[8:8+length]
if 8+length == len(data):
end = True
else:
data = data[8+length:]
elif length == 127:
length = struct.unpack("!Q", data[2:10])[0]
mask = data[10:14]
text = data[14:14+length]
if 14+length == len(data):
end = True
else:
data = data[14+length:]
unMaskedText = ""
for i,v in enumerate(text):
_unMaskedText = hex(int(binascii.b2a_hex(text[i]),16) ^ int(binascii.b2a_hex(mask[i%4]),16))[2:]
if len(_unMaskedText) % 2:
_unMaskedText = "0" + _unMaskedText
unMaskedText += binascii.a2b_hex(_unMaskedText)
dataList.append(unMaskedText)
if end:
break
return dataList
def __wrapResponse(self,str):
response = ""
if self.__getDraftType() == "76":
response = '''\x00%s\xFF''' % str
elif self.__getDraftType() == "10":
token = "\x81"
length = len(str)
if length < 126:
token += struct.pack("B", length)
elif length <= 0xFFFF:
token += struct.pack("!BH", 126, length)
else:
token += struct.pack("!BQ", 127, length)
response = '''%s%s''' % (token,str)
return response
所有接收进来的消息,都先过一下parseRequire方法,得到一个明文的数组,如果recv的消息没有合并,数组的长度当然是1,但如果recv的消息是已经合并后的,那么parseRequire会将合并的消息拆解开来,将明文返回出来。
所有发送的消息,都通过wrapResponse包装一下,再发送回客户端。
总算是将这头疼的破问题给解决了,希望不要再出差子骚扰我了 @_@,阿门。