zoukankan      html  css  js  c++  java
  • websocket协议 draft10

        我去,昨晚websocket还工作得好好的,今早就发现不能用了。检查了一圈发现原来是chrome升级到14后,支持的websocket协议改变了,不再是之前的76草案,改为支持draft-10草案了。从75草案开始,这已经是我知道的第三个握手协议方案了。google chrome团队的博客说,这应该是最后一次稳定的版本了,应该不会再改变了,可以将其应用到生产环境中:http://infra.sunway.dk/cms/fh3aggregator/sources/34#iid-189713

        另外几个可以看看的资料如下:

    http://www.codeproject.com/KB/HTML/Web-Socket-in-Essence.aspx#BrowserSupport

    http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10

         

        好吧,在safari跟上来以前,我还是将两种握手协议都封装一下吧。代码贴出来:

        def __handshakeHandler(self,data):

            response = ""

            if re.findall(r'Sec-WebSocket-Key: (.*)\n',data):

                key = re.findall(r'Sec-WebSocket-Key: (.*)\n',data)[0].strip()

                MAGIC_KEY = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 

                token = base64.b64encode(hashlib.sha1(key+MAGIC_KEY).digest())

                response = '''

    HTTP/1.1 101 Switching Protocols\r

    Upgrade: websocket\r

    Connection: Upgrade\r

    Sec-WebSocket-Accept: %s\r\n\r

    '''.lstrip() % token

            else:

                resource = re.compile("GET (.*) HTTP").findall(data)[0]

                host = re.compile("Host: (.*)\r\n").findall(data)[0]

                origin = re.compile("Origin: (.*)\r\n").findall(data)[0]

                num1 = re.findall(r'Sec-WebSocket-Key1: (.*)\n',data)[0]

                num2 = re.findall(r'Sec-WebSocket-Key2: (.*)\n',data)[0]

                key = re.findall(r'\r\n\r\n(.*)$',data)[0]

                num1_num = int("".join(re.findall(r'\d',num1)))

                num1_space = len(re.findall(r' ',num1))

                num2_num = int("".join(re.findall(r'\d',num2)))

                num2_space = len(re.findall(r' ',num2))

                token = "%s%s%s" % (struct.pack('>L',num1_num/num1_space),struct.pack('>L',num2_num/num2_space),key)

                token = hashlib.md5(token).digest()

                response = '''

    HTTP/1.1 101 WebSocket Protocol Handshake\r

    Upgrade: WebSocket\r

    Connection: Upgrade\r

    Sec-WebSocket-Origin: %s\r

    Sec-WebSocket-Location: ws://%s/\r

    Sec-WebSocket-Protocol: sample\r\n\r

    %s'''.strip() % (origin,host,token)

            self.transport.write(response)



    握手协议改好了就完了吗?NO!!!恶梦才刚开始,现在发送和接收数据也变了规则,新规则坑爹得很啊,看得我那个想死啊!!!

    参考地址如下:http://blog.vunie.com/implementing-websocket-draft-10

    好吧,终于用python写出了通信的代码,如下:

    [ 接收消息 ] 

                if draftType == "76":

                    data = data[1:-1]

                elif draftType == "10":

                    if data[0] != "\x81": return

                    length = int(binascii.b2a_hex(data[1]),16) & 0x7f 

                    if length < 126:

                        mask = data[2:6]

                        text = data[6:]

                    elif length == 126:

                        mask = data[4:8]

                        text = data[8:]

                    elif length == 127:

                        mask = data[10:14]

                        text = data[14:]

                    unMaskedText = ""

                    for i,v in enumerate(text):

                        unMaskedText += binascii.a2b_hex(hex(int(binascii.b2a_hex(text[i]),16) ^ int(binascii.b2a_hex(mask[i%4]),16))[2:])

                    data = unMaskedText

    ===================================================
    [发送消息]

        response = ""

        if draftType == "76":

            response = '''\x00%s\xFF''' % str

        elif draftType == "10":

            token = "\x81"

            length = len(str)

            if length < 126:

                token += binascii.a2b_hex(hex(length)[2:])

            elif length < 65535:

                token += binascii.a2b_hex(hex(126)[2:])

                _a = hex(length>>8)[2:]

                if len(_a) % 2:

                    _a = "0"+_a

                token += binascii.a2b_hex(_a)

                _b = hex(length & 0xff)[2:]

                if len(_b) % 2:

                    _b = "0"+_b

                token += binascii.a2b_hex(_b)

            else:

                print "I don't know how to do T_T"

            response = '''%s%s''' % (token,str)


    好吧,也许你也注意到了 “else:

    print "I don't know how to do T_T"

    ” 

    当需发送的字符串长度超过65535的时候,我们需要用8个字节来表示他的长度,而我在这里不知道如何处理了,因为参考的那篇博客里用的是nodejs,而且他没有讲到如何处理这种情况,所以我在这里不知道怎么办了。。。好在,一般情况下,我们是不会需要这么长的发送量的,我将一个二进制图片base64一下,长度也没超过,所以正常情况下,我们没有超过这个长度的可能性,先不处理也不要紧。



    ===================================================

    更新:终于比较圆满地解决接收和发送消息了,具体方法更新在这里:http://hi.baidu.com/cly84920/blog/item/ad3979ec6ac2ab3b63d09fb2.html

  • 相关阅读:
    SQLSERVER中的sp_reset_connection存储过程的作用
    SQLSERVER数据库经常置疑的原因
    sqlserver2005数据库邮件
    SQLSERVER书签查找的通俗理解
    msdb数据库里的表究竟存储什么信息
    造成阻塞和死锁的3大原因:
    SQLSERVER中的锁资源类型RID KEY PAG EXT TAB DB FIL
    总结一下要影响SQLSERVER锁的申请和释放行为要考虑的因素
    Linux下getsockopt/setsockopt 函数说明
    HTTP协议详解(转)
  • 原文地址:https://www.cnblogs.com/cly84920/p/4426572.html
Copyright © 2011-2022 走看看