简体   繁体   中英

How to reconnect to a Web Socket when I refresh the client web page

When I refresh my client web-page, I stop receiving data from a tornado socket server. How can I reconnect to the stream?

I have tried appending the connection objects to a list and then deleting the connection from the list when it closes but it turns out, when you refresh the page, the connection never closes, it stays active according to the server, but it also does not receive data anymore on the client side:(

This is my tornado server

# python 3
from tornado import web, httpserver, ioloop, websocket, options
from time import time, sleep


class ChannelHandler(websocket.WebSocketHandler):
    """Handler that handles a websocket channel"""
    connections = list()

    @classmethod
    def urls(cls):
        return [(r'/websocket', cls, {})]

    def initialize(self):
        self.channel = None

    def open(self):
        # When Client opens a websocket
        # add the new connnection to connections
        self.connections.append(self)

    def on_message(self, message):
        # Message received on channel
        # keep sending all connected clients the time info
        while True:
            [client.write_message({'time()': str(time())}) for client in self.connections]
            sleep(1)
            print('still sending')

    def on_close(self):
        # Channel is closed
        # delete client from active connections if they close connection
        self.connections.remove(self)
        print('CLOSED connection?')

    def check_origin(self, origin):
        # Override the origin check if needed
        return True


def main():
    # Create tornado application and supply URL routes
    app = web.Application(ChannelHandler.urls())
    # Setup HTTP Server
    http_server = httpserver.HTTPServer(app)
    http_server.listen(8000, 'localhost')
    # Start IO/Event loop
    ioloop.IOLoop.instance().start()


if __name__ == '__main__':
    main()

And the socket client is

<script type="text/javascript">
    var ws = new WebSocket("ws://localhost:8000/websocket");
    ws.onopen = function () {
        ws.send("Hello, world");
    };
    ws.onmessage = function (evt) {
        console.log(evt.data);
    };
</script>

So, How can I keep receiving data from a socket server when I refresh my cleint web-page?

The while loop is blocking your whole server. You've added a sleep(1) call in the loop to pause the loop for a second, but time.sleep is a blocking function, hence it's not any help either.

You need to use an asynchronous alternative to time.sleep —Tornado's gen.sleep .

You'll also need to convert the on_message function to a coroutine.

Example:

from tornado import gen


async def on_message(...):
    ...
    while True:
        ...
        await gen.sleep(1)
        ...

As an additional tip , use a set() instead of a list() to store your connections so that you don't accidentally add duplicate connections.

In this case, you'll also need to amend your code a little bit. set doesn't have an append method, instead it has an add method.

connections = set()
...
self.connections.add(self) # to add connection
...
self.connections.remove(self) # to remove connetion

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM