Search code examples
python-3.xwebsockettwistedautobahn

Is there any method to detect sendMessage() of WebSocketClientProtocol actually delivers message to server or not?


I am using "autobahn library with twisted" in python to create web-socket server and client. There is situation when my server may be down, But client is continuously sending some data packets to server using 'sendMessage()'. In this case, I experience data packet loss. Is there any way so that i can find out whether my data packet is received at server end properly or it fails to reach server ?

I have implemented onClose() method provide by WebSocketClientProtocol, this is just giving me an idea wen web socket connection is lost. But it does not solve my issue. Because my hello() in code is running after every 1 sec & sending packets to server regardless of server is running or not.

# this method is provide by WebSocketClientProtocol class, automatically triggers wen connection is established. According to my requirement hello() method should be continuously running and notify me wen there is no server to listen
def onOpen(self):
        print("WebSocket connection open.")
        def hello():
            b = bytearray([0x11, 0x01, 0x00, 0x01, 0x00])
            self.sendMessage(bytes(b), isBinary=True)
            self.factory.reactor.callLater(1, hello)

        # start sending messages every second ..
        hello()

When Web socket server is running, it should receive bytes of data packets from client. But in case it is down then, before calling 'self.sendMessage(bytes(b), isBinary=True)', i should somehow want to know status of server(running/stopped). So that i can stop my data packet loss


Solution

  • I assume you are running your WebSocket over a TCP connection.

    TCP guarantees either message delivery or notification of a lost connection. There are some tricky corner cases that must be considered in general (for example, perhaps your message is delivered and then the connection is lost and then you wait for a response; the guarantees for being notified of the connection loss are different in this case). However, in your case, where you send a message every second, the guarantee is very simple. If the connection is lost then at worst the next message you send will start a short timer that eventually results in your application being notified of the lost connection.

    Autobahn exposes such a notification to you via the onClose protocol method.

    So:

    class YourWebSocketClientProtocol(...):
        def onOpen(self):
            print("WebSocket connection open.")
            self.still_connected = True
            def hello():
                if self.still_connected:
                    b = bytearray([0x11, 0x01, 0x00, 0x01, 0x00])
                    self.sendMessage(bytes(b), isBinary=True)
                    self.factory.reactor.callLater(1, hello)
    
            # start sending messages every second ..
            hello()        
    
        def onClose(self, ...):
            self.still_connected = False
    

    Or, somewhat more simply:

    from twisted.internet.task import LoopingCall
    
    class YourWebSocketClientProtocol(...):
        def onOpen(self):
            print("WebSocket connection open.")
            def hello():
                b = bytearray([0x11, 0x01, 0x00, 0x01, 0x00])
                self.sendMessage(bytes(b), isBinary=True)
                self.factory.reactor.callLater(1, hello)
    
            # start sending messages every second ..
            self._hello = LoopingCall(hello)
            d = self._hello.start(1.0)
            d.addErrback(... handle problems ...)
    
    
        def onClose(self, ...):
            self._hello.stop()