我正在使用稍微修改过的(额外的 try)代码测试基于浏览器的 websockets from the documentation :
(后端)
import asyncio
import datetime
import random
import websockets
async def time(websocket, path):
print("new connection")
while True:
now = datetime.datetime.utcnow().isoformat() + 'Z'
try:
await websocket.send(now)
except websockets.exceptions.ConnectionClosed:
print("connection closed")
await asyncio.sleep(random.random() * 3)
start_server = websockets.serve(time, '127.0.0.1', 5678)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
(前端)
<!DOCTYPE html>
<html>
<head>
<title>WebSocket demo</title>
</head>
<body>
<script>
var ws = new WebSocket("ws://127.0.0.1:5678/"),
messages = document.createElement('ul');
ws.onmessage = function (event) {
var messages = document.getElementsByTagName('ul')[0],
message = document.createElement('li'),
content = document.createTextNode(event.data);
message.appendChild(content);
messages.appendChild(message);
};
document.body.appendChild(messages);
</script>
</body>
</html>
当启动后端并在浏览器 (Chrome) 中打开前端 .html 文件时,我得到了预期的
new connection
在后端输出上,浏览器填充了时间戳。
重新加载页面 (F5) 后,我再次获得一个新连接,然后是正在进行的连接关闭:
new connection
new connection
connection closed
connection closed
connection closed
connection closed
connection closed
与此同时,浏览器按预期运行,填充了时间戳。
这是怎么回事? 为什么第一次连接稳定,重新加载页面后连接不稳定?是否自动重新创建了与 websocket 的连接(看起来如此,因为浏览器事件正常)——但在那种情况下,是什么导致它首先被关闭?
请您参考如下方法:
您捕捉到 websockets.exceptions.ConnectionClosed 异常,这就是 websockets 知道注销已关闭连接的方式。 因此,关闭的连接永远不会取消注册。消息不断通过它发送。
您可以通过执行以下任一操作来克服此问题:
- 没有捕捉到异常。
- 通过连接的套接字发送消息
if websocket.open:
websocket.send(now)
# this doesn't unregister the closed socket connection.
- 从 websocket 服务器显式注销已关闭的套接字连接
websocket.ws_server.unregister(websocket)
# This raises an exception as well
- 在内存中维护已连接客户端的列表,向此列表中的连接发送消息,并在捕获到异常时从此列表中删除已关闭的连接。
connect.append()
await asyncio.wait([ws.send("Hello!") for ws in connected])
