如何让客户端响应Tornado WebSocket的Ping请求以避免断开?
解决Tornado WebSocket Ping/Pong自动响应问题
针对你的场景,我分别给Python websocket 模块客户端和浏览器端WebSocket客户端提供解决方案:
一、Python websocket模块客户端(websocket-client库)
默认情况下,websocket-client 库不会自动响应服务器发送的Ping帧,所以需要我们手动添加Ping回调来发送Pong响应。
步骤1:确保安装了websocket-client库
如果还没安装,先执行:
pip install websocket-client
步骤2:编写带自动Ping响应的客户端代码
在客户端中,通过设置on_ping回调函数,当收到服务器的Ping帧时自动发送Pong:
import websocket def on_ping(ws, message): # 收到Ping后立即发送Pong响应 ws.send_pong(message) def on_message(ws, message): print(f"收到消息: {message}") def on_error(ws, error): print(f"错误发生: {error}") def on_close(ws, close_status_code, close_msg): print("连接已关闭") def on_open(ws): print("连接已建立") if __name__ == "__main__": ws = websocket.WebSocketApp( "ws://your-server-url:port/ws", on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close, on_ping=on_ping # 绑定Ping回调 ) # 保持连接运行 ws.run_forever()
这样配置后,客户端收到Tornado发送的Ping帧时,会自动回复Pong,服务器就不会因为超时断开连接了。
二、浏览器端WebSocket客户端
现代浏览器的原生WebSocket API会自动响应Ping控制帧,不需要你手动编写代码处理。但如果你的浏览器客户端还是出现被服务器断开的情况,可能是以下原因:
- 你的客户端代码不小心拦截了控制帧(不过浏览器默认不会把Ping/Pong触发
message事件,所以这种情况很少见) - 浏览器所在的网络环境存在防火墙/代理,阻断了Ping/Pong帧
- 服务器的
websocket_ping_timeout设置过短
正常的浏览器客户端示例代码
你只需要保持常规的WebSocket连接逻辑即可,浏览器会自动处理Ping/Pong:
const ws = new WebSocket("ws://your-server-url:port/ws"); ws.onopen = () => { console.log("连接已建立"); }; ws.onmessage = (event) => { console.log("收到消息:", event.data); }; ws.onerror = (error) => { console.error("错误发生:", error); }; ws.onclose = (event) => { console.log("连接已关闭", event.code, event.reason); };
如果还是出现断开问题,可以检查服务器的Tornado配置,建议同时设置websocket_ping_timeout(比如设为30秒),给客户端足够的响应时间:
app = tornado.web.Application( [ (r"/ws", YourWebSocketHandler), ], websocket_ping_interval=60, websocket_ping_timeout=30 # 添加超时设置 )
内容的提问来源于stack exchange,提问作者amir ghorbani




