码迷,mamicode.com
首页 > 编程语言 > 详细

python--websocket数据解析

时间:2018-07-03 23:57:02      阅读:280      评论:0      收藏:0      [点我收藏+]

标签:cep   cross   xtend   执行   格式化   websocket   pytho   sha1   nbsp   

# websocket实现原理
‘‘‘
1.服务端开启socket,监听ip和端口
2.客户端发送连接请求(带上ip和端口)
3.服务端允许连接
4.客户端生成一个随机字符串,和magic string组合进行一个sha1加密,加密。并将随机字符串发送给服务端
5.然后服务端也要用相同的方式进行加密。
6.然后服务端将加密之后的密串返回给客户端
7.客户端将服务端返回的密串和自己加密之后的密串进行比对,如果一样,说明遵循同样的协议。如果不一样,就没法玩了·····
‘‘‘

import socket
import base64
import hashlib
from pprint import pprint


def get_headers(data):
    """
    将请求头格式化成字典
    :param data:
    :return:
    """
    header_dict = {}
    data = str(data, encoding=‘utf-8‘)

    header, body = data.split(‘\r\n\r\n‘, 1)
    header_list = header.split(‘\r\n‘)
    for i in range(0, len(header_list)):
        if i == 0:
            if len(header_list[i].split(‘ ‘)) == 3:
                header_dict[‘method‘], header_dict[‘url‘], header_dict[‘protocol‘] = header_list[i].split(‘ ‘)
        else:
            k, v = header_list[i].split(‘:‘, 1)
            header_dict[k] = v.strip()
    return header_dict


server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((‘localhost‘, 8080))
server.listen(5)

# 等待用户连接
conn, addr = server.accept()

# 握手消息
content = conn.recv(1024)
‘‘‘
>>> print(content)

b‘GET / HTTP/1.1\r\nHost: localhost:8080\r\nConnection: Upgrade\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\nOrigin: http://localhost:63342\r\nSec-WebSocket-Version: 13\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: uuid=81a68694c772e0c62d4a5a3c256fe3e0; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2216453a8bf2bbe-09a40e8e58a866-5e442e19-1fa400-16453a8bf2c745%22%7D; Hm_lvt_2af69bc2b378fb58ae04ed2a04257ed1=1530411925; Pycharm-bdfc5fce=a920e49d-da4e-4d2f-a76e-17acfacc6462\r\nSec-WebSocket-Key: 1y6WpsSgfF80wqi3HpmrqQ==\r\nSec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n‘
‘‘‘

# 获取请求头
headers = get_headers(content)
‘‘‘
>>>pprint(headers)
{‘Cache-Control‘: ‘no-cache‘,
 ‘Connection‘: ‘Upgrade‘,
 ‘Cookie‘: ‘Pycharm-bdfc5fce=a920e49d-da4e-4d2f-a76e-17acfacc6462‘,
 ‘Host‘: ‘localhost:8080‘,
 ‘Origin‘: ‘http://localhost:63342‘,
 ‘Sec-WebSocket-Key‘: ‘RRGDeYeYSGEP9eHy85u8oQ==‘,
 ‘Sec-WebSocket-Version‘: ‘13‘,
 ‘Upgrade‘: ‘websocket‘,
 ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) ‘
               ‘like Gecko‘,
 ‘method‘: ‘GET‘,
 ‘protocol‘: ‘HTTP/1.1‘,
 ‘url‘: ‘/‘}
‘‘‘

# 规定:魔法字符串就叫这个
magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"

# 获取随机密串,并将其与魔法字符串组合
value = headers["Sec-WebSocket-Key"] + magic_string

# 进行加密,规定,只能按照此加密方式
hash_str = base64.b64encode(hashlib.sha1(bytes(value, encoding=‘utf-8‘)).digest())

response_tpl = "HTTP/1.1 101 Switching Protocols\r\n"                "Upgrade:websocket\r\n"                "Connection: Upgrade\r\n"                "Sec-WebSocket-Accept: %s\r\n"                "WebSocket-Location: ws://%s%s\r\n\r\n"

# 获取握手消息,组合魔法字符串,进行sha1加密
# 发送给客户端
response_str = response_tpl % (str(hash_str, encoding=‘utf-8‘), headers[‘Host‘], headers[‘url‘])
conn.send(bytes(response_str, encoding=‘utf-8‘))


# 也可以发送数据
def send_msg(conn, msg_bytes):
    """
    WebSocket服务端向客户端发送消息
    :param conn: 客户端连接到服务器端的socket对象,即: conn,address = socket.accept()
    :param msg_bytes: 向客户端发送的字节
    :return:
    """
    import struct

    token = b"\x81"
    length = len(msg_bytes)
    if length < 126:
        token += struct.pack("B", length)
    elif length <= 0xFFFF:
        token += struct.pack("!BH", 126, length)
    else:
        token += struct.pack("!BQ", 127, length)

    msg = token + msg_bytes
    conn.send(msg)
    return True

# 那么便可以接受数据了,注意接受的数据必须按照一定的规则才能够获取
while True:
    info = conn.recv(1024)
    payload_len = info[1] & 127
    if payload_len == 126:
        extend_payload_len = info[2:4]
        mask = info[4:8]
        decoded = info[8:]
    elif payload_len == 127:
        extend_payload_len = info[2:10]
        mask = info[10:14]
        decoded = info[14:]
    else:
        extend_payload_len = None
        mask = info[2:6]
        decoded = info[6:]

    bytes_list = bytearray()
    for i in range(len(decoded)):
        chunk = decoded[i] ^ mask[i % 4]
        bytes_list.append(chunk)
    body = str(bytes_list, encoding=‘utf-8‘)
    print(body)

    # 可以将获取的body加上新的字符
    body = body + "我是你爸"
    send_msg(conn, bytes(body, encoding="utf-8"))

  

  解包过程:(这个图来自于武sir老师的博客:https://www.cnblogs.com/wupeiqi/p/6558766.html)

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script>
        ws = new WebSocket("ws://localhost:8080/");

        //如果连接成功,会打印下面这句话,否则不会打印
        ws.onopen = function () {
            console.log(‘连接成功‘)
        };

        //接收数据,服务端有数据过来,会执行
        ws.onmessage = function (event) {
            console.log(event)
        };

        //服务端主动断开连接,会执行.
        //客户端主动断开的话,不执行
        ws.onclose = function () {  }

    </script>
</body>
</html>

  

  

  

技术分享图片

 

技术分享图片

 

python--websocket数据解析

标签:cep   cross   xtend   执行   格式化   websocket   pytho   sha1   nbsp   

原文地址:https://www.cnblogs.com/traditional/p/9260830.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!