补充个小知识点:按位与运算
按位与运算是同位都为1才为1,有一个不为1就是0
websocket_hand
1 import socket, base64, hashlib
2 import websocket_jiemi
3 import websocket_jiami
4
5 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
6 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
7 sock.bind(('127.0.0.1', 9527))
8 sock.listen(5)
9 # 获取客户端socket对象
10 conn, address = sock.accept() # 阻塞
11
12 # 获取客户端的【握手】信息
13 data = conn.recv(2048)
14 print(data)
15
16
17 """
18 b'
19 GET / HTTP/1.1\r\n
20 Host: 127.0.0.1:9527\r\n
21 Connection: Upgrade\r\n
22 Pragma: no-cache\r\n
23 Cache-Control: no-cache\r\n
24 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36\r\n
25 Upgrade: websocket\r\n
26 Origin: http://localhost:63342\r\n
27 Sec-WebSocket-Version: 13\r\n
28 Accept-Encoding: gzip, deflate, br\r\n
29 Accept-Language: zh-CN,zh;q=0.9\r\n
30 Sec-WebSocket-Key: tPWfDfGthkhhqfY4ZdT1yQ==\r\n
31 Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n'
32 """
33 #
34 # # magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11
35 magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
36 #
37 #
38 def get_headers(data):
39 header_dict = {}
40 header_str = data.decode("utf8")
41 for i in header_str.split("\r\n"):
42 if str(i).startswith("Sec-WebSocket-Key"):
43 header_dict["Sec-WebSocket-Key"] = i.split(":")[1].strip()
44
45 return header_dict
46
47 headers = get_headers(data) # 提取请求头信息
48
49 # # 对请求头中的sec-websocket-key进行加密
50
51 #
52 value = headers['Sec-WebSocket-Key'] magic_string # jtl/vockZ8GRyadFVeiUTA==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
53 print(value)
54 sha1_value = hashlib.sha1(value.encode('utf-8')).digest()
55 print("sha1_value",sha1_value)
56 ac = base64.b64encode(sha1_value)
57 print("ac",ac)
58 # ac - sha1(sec magic) - base64
59 response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \
60 "Upgrade:websocket\r\n" \
61 "Connection: Upgrade\r\n" \
62 "Sec-WebSocket-Accept: %s\r\n" \
63 "WebSocket-Location: ws://127.0.0.1:9527\r\n\r\n"
64
65 response_str = response_tpl % (ac.decode('utf-8'))
66 # 响应【握手】信息
67 conn.send(response_str.encode("utf8"))
68
69 while True:
70 msg = conn.recv(8096)
71 msg = websocket_jiemi.websocket_jiema(msg)
72
73 # conn.send("123123123123".encode("utf8"))
74 send_str = websocket_jiami.jiami("hello".encode("utf8"))
75 print(send_str)
76 conn.send(send_str)
websocket_jiami
1 import struct
2 # msg_bytes = "哎呀妈呀脑瓜疼".encode("utf8")
3 def jiami(msg_bytes):
4 token = b"\x81"
5 length = len(msg_bytes)
6
7 if length < 126:
8 token = struct.pack("B", length) # \x85$
9 elif length == 126:
10 token = struct.pack("!BH", 126, length)
11 else:
12 token = struct.pack("!BQ", 127, length)
13
14 msg = token msg_bytes
15
16 return msg
websocket_jiemi
1 # b'\x81\x83\xceH\xb6\x85\xffz\x85'
2
3 hashstr = b'\x81\x85$\xcb>\x14L\xaeRxK'
4 # b'\x81
5 # \x85$
6 # \xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L
7 # \xaeRxK\xcb>\x14L\xaeRxK
8 # \xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK'
9
10 # 将第二个字节也就是 \x83 第9-16位 进行与127进行位运算
11
12 def websocket_jiema(hashstr):
13 print(hashstr[1])
14 payload = hashstr[1] & 127
15 print(payload)
16
17 if payload == 127:
18 extend_payload_len = hashstr[2:10] # 834473503
19 mask = hashstr[10:14]
20 decoded = hashstr[14:]
21 # 当位运算结果等于127时,则第3-10个字节为数据长度
22 # 第11-14字节为mask 解密所需字符串
23 # 则数据为第15字节至结尾
24 #
25
26 # b'\x81
27 # \x85$ 126
28 # \xcb>\x14L 120
29 # \xaeRxK\xcb>\x14L\xaeRxK
30 # \xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK \xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK'
31
32
33 if payload == 126:
34 extend_payload_len = hashstr[2:4]
35 mask = hashstr[4:8]
36 decoded = hashstr[8:]
37 # 当位运算结果等于126时,则第3-4个字节为数据长度
38 # 第5-8字节为mask 解密所需字符串
39 # 则数据为第9字节至结尾
40 #
41 # b'\x81
42 # \x85$ 5 len数据长度
43 # \xcb>\x14L\xaeRxK'
44
45 if payload <= 125:
46 extend_payload_len = payload
47 mask = hashstr[2:6]
48 decoded = hashstr[6:] # 5
49
50 # 当位运算结果小于等于125时,则这个数字就是数据的长度
51 # 第3-6字节为mask 解密所需字符串
52 # 则数据为第7字节至结尾
53 #
54 str_byte = bytearray()
55 #
56 for i in range(len(decoded)):
57 byte = decoded[i] ^ mask[i % 4]
58 str_byte.append(byte)
59 #
60 return str_byte.decode("utf8")
my_socket
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6 </head>
7 <body>
8
9 </body>
10 <script>
11 var ws = new WebSocket("ws://127.0.0.1:9527")
12 ws.onmessage = function (data) {
13 console.log(data.data)
14
15 }
16 </script>
17 </html>
更多专业前端知识,请上 【猿2048】www.mk2048.com