Search code examples
tornado

Websocket client is not calling on_message_callback() function when it receives a message from server


I want a server and a client to communicate to each other.

Client side:

@gen.coroutine
def connect(self):
    print("trying to connect")
    try:
        self.ws = yield websocket_connect(self.url, connect_timeout=99999, on_message_callback=on_message)
    except Exception as e:
        print("connection error : {}".format(e))

       print("connected")

But here there is no call of on_message whenever its server send message. Do you have any idea of these?


Solution

  • Well, I took a look at the source code. I can't pinpoint the problem as I don't understand what most of it is doing.

    But I noticed certain things that I think might be causing the problems. For example this code block:

    response = yield self.ws.read_message(callback=self.cb_receive_weight)
    
    ...
    
    if response.done() :
    

    This will raise an error. response is not a future, but the actual websocket message string. So, it will raise an AttributeError that it doesn't have a done() method.

    Second, callback=self.cb_receive_weight this will call the cd_receive_weight method with a future, not the message. So, that won't work.

    I think things are not working as expected is maybe because you're mixing yield and callbacks.


    Remember, yield object will automatically call object.result(). Consider:

    response = yield self.ws.read_message()
    

    Above, ws.read_message() returns a Future, but yield, will wait until the Future has a result. When the Future gets resolved, yield will call its result() method. And response will be equal to that result.

    You don't really need to use callbacks if you're using yield. I'd suggest not using callback style of coding at all. Just avoid them and use coroutines (yield) where possible.

    The code will be shorter and much more organised.

    Example:

    @gen.coroutine
    def connect(self):
        self.ws = yield websocket_connect(url)
    
        self.run()
    
    ...
    
    @gen.coroutine
    def get_weight_from_global_network(self):
    
        while True:
            response = yield self.ws.read_message()
    
            # do something with the response
    
            self.cb_recieve_weight(weight=response)
    

    Although, I can't say if this will solve your problem.