invisibleroads / socketIO-client

A socket.io client library for Python
http://pypi.python.org/pypi/socketIO-client
MIT License
447 stars 205 forks source link

Automatic Reconnect #141

Open randellhodges opened 7 years ago

randellhodges commented 7 years ago

Is there a way for the client to detect a network loss and reconnect?

I tried .wait() then I tried with a .wait(seconds=15) and then look at the .connected probably and it is always true. I would get the app up and running and then pull the network cable for about a minute. The connected property always said true and even after plugging it back in, nothing happened. It was pretty much dead.

Am I doing something wrong? Any examples with auto reconnect? I see that it is suppose to send a ping on another thread. Maybe that isn't bubbling back up to me? Should that cause the wait method to unblock and exit or at least throw while I'm "wait"ing?

This was with v0.6.5

DaniyalGeek commented 7 years ago

same issue @randellhodges did you find any answer?

invisibleroads commented 7 years ago

Have you tried the latest release? https://pypi.python.org/pypi/socketIO-client/0.7.2

Auto reconnect should work. I don't remember having issues with it.

from socketIO_client import SocketIO, BaseNamespace

class Namespace(BaseNamespace):

    def on_connect(self):
        print('[Connected]')

    def on_reconnect(self):
        print('[Reconnected]')

    def on_disconnect(self):
        print('[Disconnected]')

socketIO = SocketIO('localhost', 8000, Namespace)
socketIO.wait(seconds=30)

You might want to try a variation of the code snippet above to see what is happening.

randellhodges commented 7 years ago

First disclaimer: I am extremely new to python.

I was on 0.6.5. The latest versions didn't work for me. I think it was due to a dependency issue. I did a variation of the above, and it would reconnect. I was basically timing the pings and if I missed a ping, I would reconnect.

It is probably not how I should do it, and I am new to python.

I capture the current time in _on_socket_pong and I also get the ping timeout from socketIO in the connect. When wait stops blocking, I look to see if we missed a scheduled pong, and if so, I let the loop exit and it reconnects. I run this in it's own thread.

I know it breaks a few rules regarding encapsulation and the disclaimer is, it works for me, on the server I was hitting and for the version I was using.

    def _on_socket_connect(self, socket):

        # We will try to see what our ping check should be. It does use _variables, so
        # we'll have a fallback value
        try:
            interval = socket._engineIO_session.ping_interval
            if timeout > 0:
                self.ping_interval = interval
        except:
            pass

        try:
            timeout = socket._engineIO_session.ping_timeout
            if timeout > 0:
                self.ping_timeout = timeout
        except:
            pass

        self.last_pong = time.time()

    def _on_socket_pong(self, data):
        self.last_pong = time.time()

    def _on_socket_response(self, *args):
        self.last_pong = time.time()

     def _run(self):

        while not self.stopped.isSet():

            try:
                with self.SocketIO(STREAM_URL, params=self.params) as socket:

                    socket.on('connect', lambda: self._on_socket_connect(socket))
                    socket.on('pong', self._on_socket_pong)

                    # Note: ping_timeout and ping_interval may adjust after the initial connection
                    while not self.stopped.isSet():

                        # We need to wait for at least our ping interval, otherwise the wait will
                        # trigger a ping itself.
                        socket.wait(seconds=self.ping_timeout)

                        # Check that we have gotten pongs or data sometime in
                        # the last XX seconds. If not, we are going to assume we need
                        # to reconnect
                        now = time.time()
                        diff = int(now - (self.last_pong or now))

                        if diff > self.ping_interval:
                            break

            except (TimeoutError, ConnectionError, ConnectionResetError):
                # We are going to ignore these and go back thru the loop
                time.sleep(5)
khanhvu161188 commented 7 years ago

@invisibleroads do you have time for this issue?