Python之WebSocket学习笔记
一种基于Socket实现的多客户端WebSocketServer
import base64
import hashlib
import socket
from struct import pack, unpack
import threading
import json
class WebSocketConn:
def init(self, conn):
self.conn = conn
request = self.conn.recv(1024).strip().decode(‘utf-8’, ‘ignore’).split(‘\r\n’)
print(request)
# parse headers into dict
self.headers = dict([line.split(‘: ‘, 1) for line in request[1:]])
print(self.headers)
# perform WebSocket handshake
self._handshake(
def _handshake(self):
key = self.headers.get(‘Sec-WebSocket-Key’) + ‘258EAFA5-E914-47DA-95CA-C5AB0DC85B11’
resp_key = base64.standard_b64encode(hashlib.sha1(key.encode()).digest()).decode()
res_header = {
‘Upgrade’: ‘websocket’,
‘Connection’: ‘Upgrade’,
‘Sec-WebSocket-Accept’: resp_key,
}
response = ‘HTTP/1.1 101 Switching Protocols\r\n’
for i in res_header:
response += ‘%s: %s\r\n’ % (i, res_header[i])
response += ‘\r\n’
print(response)
self.conn.send(response.encode()
def recv(self):
”’
retrieve data from the client.
”’
buffer = self.conn.recv(2)
if buffer:
# read the three possible content-length number
length = buffer[1] – 2 ** 7
if length == 126:
length, = unpack(‘>H’, self.conn.recv(2))
elif length == 127:
length, = unpack(‘>Q’, self.conn.recv(8))
# get the masking key for the content
mask = self.conn.recv(4)
# encoded content
buffer = self.conn.recv(length)
decoded = ”
for i in range(length):
# decode the content
decoded += chr(buffer[i] ^ mask[i % 4])
return decoded
def send(self, data):
”’
send content in form of WebSocket data frame.
”’
buffer = b”
# initial 4 bits
buffer += pack(‘>B’, 129
# length of the conten
if len(data) > 126:
if len(data) < 2 ** 10: buffer += pack(‘>BH’, 126, len(data))
else:
buffer += pack(‘>BQ’, 127, len(data))
else:
buffer += pack(‘>B’, len(data))
# append content
buffer += data.encode()
self.conn.send(buffer)
def close(self):
”’
close the connection.
”’
self.conn.close()
class WebSocket:
def __init__(self, addr):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
self.sock.bind(addr)
def listen(self, num):
self.sock.listen(num)
def accept(self):
conn, self.addr = self.sock.accept()
self.conn = WebSocketConn(conn)
return self.conn, self.addr
class WebSocketServer:
def __init__(self, sock):
self.sock = sock
self.player_pool = []
def run(self):
lock = threading.Lock()
while True:
conn, addr = self.sock.accept()
threading.Thread(target=self.handle, args=(conn, addr, lock)).start()
def handle(self, conn, addr, lock):
while True:
try:
buffer = conn.recv()
print(buffer)
if buffer:
try:
req = json.loads(buffer.strip())
except Exception as e:
print(e)
if req.get(‘init’):
conn.send(json.dumps({‘init’: 1, ‘id’: len(self.player_pool)}))
else:
if req.get(‘id’) >= len(self.player_pool):
lock.acquire()
self.player_pool.append(req)
lock.release()
else:
self.player_pool[req.get(‘id’)] = req
conn.send(json.dumps(self.player_pool))
except Exception as e:
conn.close()
return 0
if __name__ == ‘__main__’:
sock = WebSocket((‘0.0.0.0’, 10002))
sock.listen(10)
server = WebSocketServer(sock)
server.run()
基于python-websocket-server模块实现的WebSocket Server
python-websocket-server的安装:pip install git+https://github.com/Pithikos/python-websocket-server
(latest code)
import logging
from websocket_server import WebsocketServer
def new_client(client, server):
server.send_message_to_all(“Hey all, a new client has joined us”)
def left_client(client, server):
server.send_message_to_all(“Hey all, a new client has jleft us”)
def receive_message(client, server, message):
print(message)
server.send_message(client, message)
server = WebsocketServer(13254, host=’192.168.10.23′, loglevel=logging.INFO)
server.set_fn_new_client(new_client)
server.set_fn_client_left(left_client)
server.set_fn_message_received(receive_message)
server.run_forever()
基于websocket_client模块实现的WebSocket Client
websocket_client的安装:pip install websocket-client