zoukankan      html  css  js  c++  java
  • websocket

    websocket: 流程

    ws 请求
    sec-WebSocket-key: 前端传过来的,会变
    magic_string: #固定值
    加密后返回,建立连接 (服务端加密)

    客户端发送的消息,服务端解密后查看
    服务端发送加密的信息


    解密:
    与位运算 最大127
    前端传过来(数据长度,解密所需字符串,数据)

    加密:后台加密后传过去数据

    import socket, base64, hashlib
    import websocket_jiemi
    import websocket_jiami
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('127.0.0.1', 9527))
    sock.listen(5)
    # 获取客户端socket对象
    conn, address = sock.accept() # 阻塞
    
    # 获取客户端的【握手】信息
    data = conn.recv(2048)
    print(data)
    
    
    """
    b'
    GET / HTTP/1.1
    
    Host: 127.0.0.1:9527
    
    Connection: Upgrade
    
    Pragma: no-cache
    
    Cache-Control: no-cache
    
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
    
    Upgrade: websocket
    
    Origin: http://localhost:63342
    
    Sec-WebSocket-Version: 13
    
    Accept-Encoding: gzip, deflate, br
    
    Accept-Language: zh-CN,zh;q=0.9
    
    Sec-WebSocket-Key: tPWfDfGthkhhqfY4ZdT1yQ==
    
    Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
    
    '
    """
    #
    # # magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11 #固定值
    magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
    #
    #
    def get_headers(data):
        header_dict = {}
        header_str = data.decode("utf8")
        for i in header_str.split("
    "):
            if str(i).startswith("Sec-WebSocket-Key"):
                header_dict["Sec-WebSocket-Key"] = i.split(":")[1].strip()
    
        return header_dict
    
    headers = get_headers(data)  # 提取请求头信息 Sec-WebSocket-Key
    
    # # 对请求头中的sec-websocket-key进行加密
    
    #
    value = headers['Sec-WebSocket-Key'] + magic_string  # jtl/vockZ8GRyadFVeiUTA==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
    print(value)
    sha1_value = hashlib.sha1(value.encode('utf-8')).digest() #字节
    print("sha1_value",sha1_value)
    ac = base64.b64encode(sha1_value) #字节
    print("ac",ac)
    # ac  = base64(sha1(sec+magic))
    response_tpl = "HTTP/1.1 101 Switching Protocols
    " 
                   "Upgrade:websocket
    " 
                   "Connection: Upgrade
    " 
                   "Sec-WebSocket-Accept: %s
    " 
                   "WebSocket-Location: ws://127.0.0.1:9527
    
    "
    
    response_str = response_tpl % (ac.decode('utf-8'))
    # 响应【握手加密后的】信息
    conn.send(response_str.encode("utf8"))
    
    while True:
        msg = conn.recv(8096)
        msg = websocket_jiemi.websocket_jiema(msg)
    
        # conn.send("123123123123".encode("utf8"))
        send_str = websocket_jiami.jiami("hello".encode("utf8"))
        print(send_str)
        conn.send(send_str)
    websocket_hand.py
    # b'x81x83xceHxb6x85xffzx85'
    
    hashstr = b'x81x85$xcb>x14LxaeRxK'
    # b'x81
    # x85$
    # xcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14L
    # xaeRxKxcb>x14LxaeRxK
    # xcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxK'
    
    # 将第二个字节也就是 x83 第9-16位 进行与127进行位运算
    
    def websocket_jiema(hashstr):
        print(hashstr[1])
        payload = hashstr[1] & 127
        print(payload)  #位运算后的结果
    
        if payload == 127:
            extend_payload_len = hashstr[2:10] # 834473503 数据长度
            mask = hashstr[10:14] #解密所需字符串
            decoded = hashstr[14:] #数据
        # 当位运算结果等于127时,则第3-10个字节为数据长度
        # 第11-14字节为mask 解密所需字符串
        # 则数据为第15字节至结尾
        #
    
        # b'x81
        # x85$    126
        # xcb>x14L 120
        # xaeRxKxcb>x14LxaeRxK
        # xcb>x14LxaeRxKxcb>x14LxaeRxK xcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxK'
    
    
        if payload == 126:
            extend_payload_len = hashstr[2:4]
            mask = hashstr[4:8]
            decoded = hashstr[8:]
        # 当位运算结果等于126时,则第3-4个字节为数据长度
        # 第5-8字节为mask 解密所需字符串
        # 则数据为第9字节至结尾
        #
        #   b'x81
        # x85$ 5 len数据长度
        # xcb>x14LxaeRxK'
    
        if payload <= 125:
            extend_payload_len = payload
            mask = hashstr[2:6]
            decoded = hashstr[6:]  # 5
    
        # 当位运算结果小于等于125时,则这个数字就是数据的长度
        # 第3-6字节为mask 解密所需字符串
        # 则数据为第7字节至结尾
        #
        str_byte = bytearray() #字节的列表,里面存放传过来的字节,自动拼成字节串
        #
        for i in range(len(decoded)):
            byte = decoded[i] ^ mask[i % 4] #或运算
            str_byte.append(byte)
        #
        return str_byte.decode("utf8")  #解密运算完后的前端穿过来的信息
    websocket_jiemi.py
    import struct  #加密使用
    # msg_bytes = "哎呀妈呀脑瓜疼".encode("utf8")
    def jiami(msg_bytes):
        token = b"x81"
        length = len(msg_bytes) #发送到客服端的真实数据的字节长度
    
        # 该模块可以把一个类型,如数字,转成固定长度的bytes
        # struct.pack('i',1111111111111)
    
        if length < 126:
            token += struct.pack("B", length) # x85$
        elif length == 126:
            token += struct.pack("!BH", 126, length)
        else:
            token += struct.pack("!BQ", 127, length)
    
        msg = token + msg_bytes
    
        return msg #加密后的字节信息
    websocket_jiami.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    </body>
    <script>
        var ws = new WebSocket("ws://127.0.0.1:9527")
        ws.onmessage = function (data) {
            console.log(data.data)
    
        }
    </script>
    </html>
    my_socket.html
  • 相关阅读:
    Unity3D 开发之shader教程(浅谈光照之漫反射diffuse)
    Unity3D 开发之shader教程(实现圆角矩形)
    Unity3D 开发之shader教程(实时swirl 扭曲漩涡效果)
    lerp function(线性插值计算)
    关于Lua以及UniLua的学习与笔记(随时更新)
    Android SDK Manager 更新
    Mac OS X 安装protobuf 2.6.1
    IDFactory int类型ID生成器
    Android TextView 添加部分文字高亮,点击功能
    Android MonkeyRunner 功能测试 自动执行 挂机脚本
  • 原文地址:https://www.cnblogs.com/xujinjin18/p/9886488.html
Copyright © 2011-2022 走看看