欢迎访问宙启技术站
智能推送

利用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服务器的示例,希望对你有所帮助。