利用Python的HTTPServer()模块实现WebSocket服务器
发布时间:2024-01-02 05:55:23
WebSocket是一种在单个TCP连接上进行全双工通信的通信协议。它允许客户端和服务器之间实时地传输数据,而无需使用轮询机制或长轮询。Python的HTTPServer模块提供了一种简单的方式来实现WebSocket服务器。
要实现WebSocket服务器,首先需要了解HTTPServer模块的基本使用。HTTPServer是Python标准库中的一个模块,它提供了一个基于SocketServer的HTTP服务器类。以下是一个基本的使用例子:
import http.server
# 自定义请求处理类
class MyHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(b"Hello, world!")
# 创建HTTPServer实例并指定请求处理类
server = http.server.HTTPServer(("", 8000), MyHandler)
# 启动服务器
server.serve_forever()
上面的例子创建了一个简单的HTTP服务器,监听在本地8000端口。当接收到GET请求时,服务器会返回一个"Hello, world!"的响应。
要实现WebSocket服务器,我们可以在HTTPServer的基础上进行进一步扩展。下面是一个使用WebSocket的例子:
import http.server
from http import HTTPStatus
import socketserver
import hashlib
import base64
import struct
# WebSocketHandler类继承自BaseHTTPRequestHandler,负责处理WebSocket请求
class WebSocketHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
if self.headers.get('Upgrade') == 'websocket':
# 当有WebSocket连接请求时,进行握手
self.handshake()
else:
# 其他情况按照普通HTTP请求处理
self.send_response(HTTPStatus.OK)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(b"Hello, world!")
def handshake(self):
# 发送101状态码和必要的头部字段,进行WebSocket握手
self.send_response(HTTPStatus.SWITCHING_PROTOCOLS)
self.send_header('Upgrade', 'websocket')
self.send_header('Connection', 'Upgrade')
key = self.headers.get('Sec-WebSocket-Key')
accept = self.calculate_accept(key)
self.send_header('Sec-WebSocket-Accept', accept)
self.end_headers()
# 接收WebSocket数据并发送回应
self.handle_websocket()
def calculate_accept(self, key):
# 根据Sec-WebSocket-Key计算Sec-WebSocket-Accept值
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
hash_object = hashlib.sha1((key + GUID).encode())
accept = base64.b64encode(hash_object.digest()).decode()
return accept
def handle_websocket(self):
# 接收WebSocket数据并发送回应
while True:
data = self.websocket_receive()
if data is None:
break
self.websocket_send(data)
def websocket_receive(self):
# 接收WebSocket数据
length_data = self.rfile.read(2)
opcode = length_data[0] & 0x0F
length = length_data[1] & 0x7F
if opcode == 0x08:
# 收到关闭帧,返回None表示结束
return None
elif length == 126:
# 数据长度超过125字节,需要额外读取2个字节获取真实长度
extended_data = self.rfile.read(2)
length = struct.unpack('!H', extended_data)[0]
elif length == 127:
# 数据长度超过65535字节,暂不支持
raise ValueError('Data length too long')
# 读取真实数据并返回
mask = self.rfile.read(4)
masked_data = self.rfile.read(length)
unmasked_data = bytearray(length)
for i in range(length):
unmasked_data[i] = masked_data[i] ^ mask[i % 4]
return unmasked_data.decode()
def websocket_send(self, data):
# 发送WebSocket数据
length = len(data)
header = bytearray(2)
header[0] = 0x81
if length < 126:
header[1] = length
self.wfile.write(header)
self.wfile.write(data.encode())
else:
raise ValueError('Data length too long')
# 创建WebSocketServer实例并指定请求处理类
server = socketserver.TCPServer(("", 8000), WebSocketHandler)
# 启动服务器
server.serve_forever()
上面的例子中,自定义的WebSocketHandler类继承自BaseHTTPRequestHandler,负责处理WebSocket的握手和数据收发。当有WebSocket连接请求时,会进行握手,之后服务器会不断接收客户端发送的数据,并发送回应。
要在浏览器中访问WebSocket服务器,可以使用JavaScript的WebSocket对象。以下是一个使用HTML和JavaScript的示例页面,用于连接WebSocket服务器并发送和接收数据:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Test</title>
<script>
var socket = new WebSocket("ws://localhost:8000/");
socket.onopen = function() {
console.log("WebSocket opened");
socket.send("Hello, server!");
};
socket.onmessage = function(event) {
console.log("Received: " + event.data);
};
socket.onclose = function(event) {
console.log("WebSocket closed: " + event.code);
};
</script>
</head>
<body>
</body>
</html>
以上是利用Python的HTTPServer模块实现WebSocket服务器的示例,希望对你有所帮助。
