zoukankan      html  css  js  c++  java
  • 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包装一下,再发送回客户端。

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

  • 相关阅读:
    Oracle11g 干净卸载
    linux中的帮助命令
    Linux Samba文件共享服务,安装与案例配置
    linux文件系统相关命令(df/du/fsck/dumpe2fs)
    虚拟机VMware下CentOS6.6安装教程图文详解
    vnc连接远端linux服务器
    mysql57重新安装后无法再次启动mysql57服务“本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动。”--解决方法
    (二)分布式数据库tidb-事务
    Centos 6下使用cmake编译安装MariaDB
    MySQL数据库基本知识
  • 原文地址:https://www.cnblogs.com/cly84920/p/4426569.html
Copyright © 2011-2022 走看看