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包装一下,再发送回客户端。

总算是将这头疼的破问题给解决了,希望不要再出差子骚扰我了 @_@,阿门。

原文地址:https://www.cnblogs.com/cly84920/p/4426569.html