赞
踩
首先通过如下代码,我们使用socket来获取客户端的握手信息
- import socket
-
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind(("127.0.0.1", 8002))
- sock.listen(5)
-
- conn, address = sock.accept() # 获取客户端的socket对象和地址
-
- msg = conn.recv(1024) # 获取客户端的握手信息
- print(msg)
我们可以通过http://www.websocket-test.com/来作为websocket客户端
当连接上服务端时,服务端打印如下信息
将上述打印信息转为JSON格式:
- def get_headers(data):
- """
- 将请求头格式化成字典
- :param data:
- :return:
- """
- header_dict = {}
- data = str(data, encoding='utf-8')
-
- # for i in data.split('\r\n'):
- # print(i)
- 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
调用上述方法可以将服务端收到的握手信息转为Json格式:
- key = headers_dict["Sec-WebSocket-Key"] # 提取key
-
- # 对key进行加密
- magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
- value = key + magic_string
- ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest())
- # print(ac)
- # 将加密的结果返回客户端
- 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"
- response_str = response_tpl % (ac.decode('utf-8'), headers_dict['Host'], headers_dict['url'])
- conn.send(response_str.encode("utf-8"))
这里建立连接后,将客户端发送的信息再返回给客户端
- while True:
- try:
- info = conn.recv(8096)
- except Exception as e:
- info = None
- if not info:
- break
- 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')
- send_msg(conn, body.encode('utf-8'))
实现了服务端接收与发送的分离;
当服务端接收到指定字符串时("exit"),服务端主动断开连接。
- import socket,base64,hashlib,time,threading
-
-
- def get_headers(data):
- """
- 将请求头格式化成字典
- :param data:
- :return:
- """
- header_dict = {}
- data = str(data, encoding='utf-8')
-
- # for i in data.split('\r\n'):
- # print(i)
- 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
-
- 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
-
- def recv_msg(conn):
- while True:
- try:
- info = conn.recv(8096)
- except Exception as e:
- info = None
- if not info:
- break
- 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)
- global body
- body = str(bytes_list, encoding='utf-8')
- print(body)
- if body == "exit":
- conn.close()
- break
-
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind(("127.0.0.1", 8002))
- sock.listen(5)
-
- conn, address = sock.accept() # 获取客户端的socket对象和地址
-
- data = conn.recv(1024) # 获取客户端的握手信息
- headers_dict = get_headers(data)
- key = headers_dict["Sec-WebSocket-Key"] # 提取key
-
- # 对key进行加密
- magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
- value = key + magic_string
- ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest())
- # print(ac)
-
- # 将加密的结果返回客户端
- 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"
- response_str = response_tpl % (ac.decode('utf-8'), headers_dict['Host'], headers_dict['url'])
- conn.send(response_str.encode("utf-8"))
-
- # 和客户端建立连接后的操作
-
- # 启动接收客户端信息的线程
- thread_obj = threading.Thread(target=recv_msg, args=(conn,))
- thread_obj.daemon = True
- thread_obj.start()
-
- # 不断给客户端发送信息
- while True:
- if getattr(conn, "_closed") == False: # 客户端没有关闭
- send_msg(conn, str("你好").encode('utf-8'))
- time.sleep(1)
- else: # 客户端关闭
- break
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。