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