Python异步WebSocket服务器处理客户端异常断连时出现[WinError 121]信号量超时错误的解决方案咨询
Python异步WebSocket服务器处理客户端异常断连时出现[WinError 121]信号量超时错误的解决方案咨询
大家好,我最近在用Python的websockets库搭建异步WebSocket服务器时碰到了个棘手的问题,想请各位帮忙出出主意。
先说说具体场景:我用的是官方提供的asyncio版服务器示例代码,但当客户端异常断开连接时(比如连接着的时候突然关掉WiFi或者拔掉网线),服务器就会抛出[WinError 121]信号量超时的错误。有意思的是,我试了官方的线程版示例,完全不会出现这个报错,所以我猜测问题应该和asyncio的实现机制有关。
问题复现步骤
- 把下面的服务器代码复制到py文件中运行
- 准备一个WebSocket客户端工具(我用的是另一台电脑上的Postman,也可以用手机端的WebSocket客户端APP)
- 确保服务器和客户端处于同一个局域网内
- 确定服务器的IP地址
- 让客户端连接到服务器
- 在保持连接的状态下,关闭客户端的网络(比如关掉WiFi、拔网线)
- 等待约30秒,就能看到[WinError 121]的报错信息
服务器代码
#!/usr/bin/env python """Echo server using the asyncio API.""" import asyncio from websockets.asyncio.server import serve async def echo(websocket): async for message in websocket: await websocket.send(message) async def main(): async with serve(echo, "0.0.0.0", 8765) as server: await server.serve_forever() if __name__ == "__main__": asyncio.run(main())
完整报错栈
connection handler failed Traceback (most recent call last): File "C:\Users\Jusuf Rrustaj\AppData\Local\Programs\Python\Python312\Lib\asyncio\proactor_events.py", line 286, in _loop_reading length = fut.result() ^^^^^^^^^^^^ File "C:\Users\Jusuf Rrustaj\AppData\Local\Programs\Python\Python312\Lib\asyncio\windows_events.py", line 803, in _poll value = callback(transferred, key, ov) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Jusuf Rrustaj\AppData\Local\Programs\Python\Python312\Lib\asyncio\windows_events.py", line 462, in finish_socket_func return ov.getresult() ^^^^^^^^^^^^^^ OSError: [WinError 121] The semaphore timeout period has expired The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\Jusuf Rrustaj\AppData\Local\Programs\Python\Python312\Lib\site-packages\websockets\asyncio\server.py", line 374, in conn_handler await self.handler(connection) File "e:\Programming\asyncio websocket\server.py", line 10, in echo async for message in websocket: File "C:\Users\Jusuf Rrustaj\AppData\Local\Programs\Python\Python312\Lib\site-packages\websockets\asyncio\connection.py", line 224, in __aiter__ yield await self.recv() ^^^^^^^^^^^^^^^^^ File "C:\Users\Jusuf Rrustaj\AppData\Local\Programs\Python\Python312\Lib\site-packages\websockets\asyncio\connection.py", line 279, in recv raise self.protocol.close_exc from self.recv_exc websockets.exceptions.ConnectionClosedError: no close frame received or sent
我期望的解决方案
我希望能修改现有代码,让服务器可以识别到客户端已经异常断开连接,并且不会抛出这类错误,而是能优雅地处理这种断连情况。
备注:内容来源于stack exchange,提问作者Jusuf Rrustaj
相关产品推荐
相关产品推荐

