WoJ
WoJ

Reputation: 30074

Why are websockets connections constantly closed upon browser reload?

I was testing browser-based websockets using the slightly adapted (extra try) code from the documentation:

(backend)

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()

(frontend)

<!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>

When starting the backend and opening the frontend .html file in a browser (Chrome), I get the expected

new connection

on the backend output, and the browser is filled in with timestamps.

After reloading the page (F5), I get again a new connection, followed by ongoing connection closed:

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

At the same time, the browser acts as expected, being filled in with timestamps.

What is happening? Why would the connection be stable the first time, and the unstable after reloading the page? Is the connection to the websocket recreated automatically (looks so, since the browser activity is OK) - but in that case what causes it to be closed in the first place?

Upvotes: 1

Views: 4076

Answers (2)

Oluwafemi Sule
Oluwafemi Sule

Reputation: 38992

You catch websockets.exceptions.ConnectionClosed exception which is how websockets knows to unregister a closed connection. The closed connection is never unregistered because of this. Messages keep being sent through it.

You can get past this by doing any of the following:

  1. Not catching the exception.
  2. Sending messages via connected sockets

if websocket.open:
    websocket.send(now)
# this doesn't unregister the closed socket connection.
  1. explicitly unregistering the closed socket connection from the websocket server

websocket.ws_server.unregister(websocket) 
# This raises an exception as well
  1. Maintaining a list of connected clients in memory, sending messages to connections in this list and removing closed connections from this list on caught exception.


connect.append()
await asyncio.wait([ws.send("Hello!") for ws in connected])

Reference

Upvotes: 3

jsbueno
jsbueno

Reputation: 110746

Because you create a new WebSocket object on each browser reload. WebSockets can be persistent, but only if the object representing them is kept alive both on server and client sides - you do nothing to preserve your Javascript websocket upon page reload and it can't be ordinarily done - you have to use other mechanisms than full page reload to communicate. On page reload, the browser just creates a new connection to the server as a new WebSockect.

Upvotes: 2

Related Questions