Using different functions to process messages in a single autobahn WebSocketProtocol

StackOverflow https://stackoverflow.com/questions/18625385

  •  27-06-2022
  •  | 
  •  

Pregunta

I am pretty new to websockets and have been trying to use python with autobahn and twisted to connect to multiple sockets and then perform different actions on the data coming from each of the different sockets.

In the end I will have 3 to 4 distinct processing functions and up to 10-15 total websocket connections.

I want to pass a function into the protocol to be used to analyze the data coming back. The problem I'm having is the only way I can figure out to access a function in the "onMessage()" method of the WebSocketClientProtocol is set for the class and not the actual object, so I'm stuck with one data processing function for all websockets.

Code example below.

from autobahn.websocket import WebSocketClientFactory, WebSocketClientProtocol
from twisted.internet import reactor, ssl

# message processing methods
def method1(self, data):
    print 'Using Method 1.'

def method2(self, data):
    print 'Using Method 2.'

# factory and protocol classes
class myFactory(WebSocketClientFactory):
    def clientConnectionLost(self, connector, reason):
        connector.connect()

class myWS(WebSocketClientProtocol):

    def initialize(self, url, data_fcn):
        self.factory = myFactory(url)
        self.factory.protocol = myWS

        # !!! set in class, not object !!!
        self.factory.protocol.data_fcn = data_fcn 

    def onMessage(self, msg, binary):
        self.data_fcn(msg)

    def onClose(self, a, b, c):
        reactor.stop()
        reactor.disconnectAll()

    def kill(self):
        self.transport.loseConnection()
        reactor.stop()
    reactor.disconnectAll()


if __name__ == '__main__':

    # websocket topics unique
    topic_ids = [ '3395',
                  '3563',
                  '3562' ]

    # data processing functions can repeat
    data_process_fcns = [ method1,
                          method2,
                          method1 ]

    for topic, func in zip(topic_ids, data_process_fcns):

        url = 'wss://mywebsocket.com/feed?topic_id[]=' + topic
        ws = myWS()
        ws.initialize(url, func)

        reactor.connectSSL(ws.factory.host, ws.factory.port, ws.factory, ssl.ClientContextFactory())

    reactor.run()

My current solution has been to create one class for each data processing function I want to use. So, for method1 I have

class myWS_method1(WebSocketClientProtocol):

with

    def onMessage(self, msg, binary):
        method1(msg)

and similar classes for each data processing method I want to use.

Was hoping to find a more elegant solution that would allow me to reuse a single class.

Thanks,

¿Fue útil?

Solución

In Twisted you hardly ever construct the Protocol yourself, its the responsibility of the Factory. I'd something like this:

class myFactory(WebSocketClientFactory):

    def __init__(self, url, data_processing):
        WebSocketClientFactory.__init__(self, url)
        # here you could have passed whatever parameters
        # later allow you to build up the protocol instance
        self._data_processing = data_processing

    def buildProtocol(self, addr):
        # Use this method to control the creation of the 
        # protocol instance.
        # You can either build a protocol here and inject
        # data_func, or use different protocol class type.

        protocol = myWs()
        protocol.data_func = self._data_processing
        return protocol

Than, the loop with connecting would look like:

for topic, func in zip(topic_ids, data_process_fcns):
    url = 'wss://mywebsocket.com/feed?topic_id[]=' + topic
    factory = myFactory(url, func)
    reactor.connectSSL(factory.host, factory.port, factory, ssl.ClientContextFactory())
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top