为什么在浏览器重新加载时,websockets连接会不断关闭?

时间:2017-08-14 13:02:29

标签: python python-3.x websocket

我使用略微调整的(try}代码from the documentation来测试基于浏览器的websockets:

(后端)

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,然后继续connection closed

new connection
new connection
connection closed
connection closed
connection closed
connection closed
connection closed

同时,浏览器按预期运行,并填入时间戳。

发生了什么事?为什么连接第一次稳定,重新加载页面后不稳定?是否自动重新创建了websocket的连接(看起来如此,因为浏览器活动正常) - 但在这种情况下是什么导致它首先被关闭?

2 个答案:

答案 0 :(得分:3)

您捕获websockets.exceptions.ConnectionClosed异常,这是websockets知道取消注册已关闭连接的方式。 因此,封闭连接永远不会注册。邮件不断通过它发送。

您可以通过执行以下任何操作来解决此问题:

  1. 没有捕获异常。
  2. 通过连接的套接字发送消息
  3. 
    if websocket.open:
        websocket.send(now)
    # this doesn't unregister the closed socket connection.
    
    1. 显式取消注册来自websocket服务器的已关闭套接字连接
    2. 
      websocket.ws_server.unregister(websocket) 
      # This raises an exception as well
      
      1. 维护内存中已连接客户端的列表,向此列表中的连接发送消息,并在捕获的异常中从此列表中删除已关闭的连接。
      2. 
        connect.append()
        await asyncio.wait([ws.send("Hello!") for ws in connected])
        

        参考

答案 1 :(得分:2)

因为您在每次浏览器重新加载时都创建了一个新的WebSocket对象。 WebSockets可以是持久的,但只有当代表它们的对象在服务器端和客户端都保持活动状态时 - 在页面重新加载时你没有做任何事情来保留你的Javascript websocket并且它通常不能完成 - 你必须使用其他机制比完整页面重新加载进行通信。在页面重新加载时,浏览器只是作为新的WebSockect创建与服务器的新连接。