Python 服务器 - 处理 WebSocket.close()

Posted

技术标签:

【中文标题】Python 服务器 - 处理 WebSocket.close()【英文标题】:Python Server - Processing WebSocket.close() 【发布时间】:2015-06-09 17:42:13 【问题描述】:

我正在使用下面提供的代码在小型服务器上工作。服务器将与 websocket 交互以从 websocket 获取消息,将消息发送回 websocket,一旦 websocket 调用.close(),服务器将“关闭”或关闭连接。

但是目前,当 websocket 调用.close() 时,断开连接的时间很长。 (我假设当没有发送 ping/pong 消息以保持连接处于活动状态时发生的 websockets 超时 300 秒)。反过来,我认为这意味着连接没有完全关闭,只是迷路了。

有没有办法确定和解决这个问题?

我一直在阅读 python 套接字服务器文档和其他各种资源以弄明白它并提出了不足。我唯一的解决方案是下面代码中的hack 注释。

    https://docs.python.org/2/library/socketserver.html

    http://pymotw.com/2/SocketServer/

    import struct
    import SocketServer
    from base64 import b64encode
    from hashlib import sha1
    from mimetools import Message
    from StringIO import StringIO
    
    class WebSocketsHandler(SocketServer.StreamRequestHandler):
    magic = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
    
    def setup(self):
        SocketServer.StreamRequestHandler.setup(self)
        print "connection established", self.client_address
        self.handshake_done = False
    
    def handle(self):
        while True:
            if not self.handshake_done:
                self.handshake()
            else:
                self.read_next_message()
    
    def read_next_message(self):
        length = ord(self.rfile.read(2)[1]) & 127
        if length == 126:
            length = struct.unpack(">H", self.rfile.read(2))[0]
        elif length == 127:
            length = struct.unpack(">Q", self.rfile.read(8))[0]
        masks = [ord(byte) for byte in self.rfile.read(4)]
        decoded = ""
        for char in self.rfile.read(length):
            decoded += chr(ord(char) ^ masks[len(decoded) % 4])
        self.on_message(decoded)
    
    def send_message(self, message):
        self.request.send(chr(129))
        length = len(message)
        if length <= 125:
            self.request.send(chr(length))
        elif length >= 126 and length <= 65535:
            self.request.send(chr(126))
            self.request.send(struct.pack(">H", length))
        else:
            self.request.send(chr(127))
            self.request.send(struct.pack(">Q", length))
        self.request.send(message)
    
    def handshake(self):
        data = self.request.recv(1024).strip()
        headers = Message(StringIO(data.split('\r\n', 1)[1]))
        if headers.get("Upgrade", None) != "websocket":
            return
        print 'Handshaking...'
        key = headers['Sec-WebSocket-Key']
        digest = b64encode(sha1(key + self.magic).hexdigest().decode('hex'))
        response = 'HTTP/1.1 101 Switching Protocols\r\n'
        response += 'Upgrade: websocket\r\n'
        response += 'Connection: Upgrade\r\n'
        response += 'Sec-WebSocket-Accept: %s\r\n\r\n' % digest
        self.handshake_done = self.request.send(response)
    
    def on_message(self, message):
        print message
        self.send_message("How do you do?")
    
    
    if __name__ == "__main__":
        server = SocketServer.TCPServer(
        ("", 9999), WebSocketsHandler)
    server.serve_forever()
    

【略】修改自:https://gist.github.com/jkp/3136208

注意:我知道server.serve_forever() 以及这可能是一个问题。我正在寻找以下方面的建议或方向:

def on_close(): ...

【问题讨论】:

【参考方案1】:

我认为您需要在服务器端实现 onClose() 方法。为什么不使用一些支持 websocket 的 python 框架,例如Tornado 或Authobahn。

这是一个使用 Tornado 在 python 中的 websocket 服务器的示例 https://developer.mbed.org/cookbook/Websockets-Server

我希望这会对你有所帮助。

【讨论】:

以上是关于Python 服务器 - 处理 WebSocket.close()的主要内容,如果未能解决你的问题,请参考以下文章

使用python 多进程进行基于websocket 的实时视频流处理

从 Python 中的 WebSocket 读取(来自 Javascript WebSocket 的数据)

HTTP 服务器外 Python3 的 Websocket 服务器

FastAPI websocket 无法处理大量数据传入?

如何在此服务器中实现 Websocket 握手?

Python Tornado Websocket 处理程序在接收数据时阻塞