How to send data using a twisted protocol through a factory

I am writing a client that implements its own protocol, and a factory for it. My problem is this: my client has two-way communication, and sometimes I want to say β€œsend this data”. But I have a factory object:

class MyFactory(ClientFactory): protocol = MyProtocol def __init__(self, recv_callback): self.recv_callback = recv_callback def send_message(self, msg): self.protocol.send_message(msg) 

So, I create a factory and have a factory object, I am not a protocol object. When send_message is send_message , I get an error because self.protocol is just a class, not an object.

How can i do this? Should I also show the protocol for the connection in addition to the factory?

thanks

+7
source share
1 answer

You have access to all the objects you want. factory is responsible for instantiating the protocol, so if you want to save the protocol instance where it can use the factory, override buildProtocol and save the instance:

 class MyFactory(ClientFactory): protocol = MyProtocol ... def buildProtocol(self, address): proto = ClientFactory.buildProtocol(self, address) self.connectedProtocol = proto return proto 

However, this approach is missing from one important function. This does not make it easy to determine when buildProtocol and connectedProtocol called. If you try to use this attribute naively:

 factory = MyFactory() reactor.connectTCP(host, port, factory) factory.connectedProtocol.send_message(...) 

The code will not work with AttributeError because the connection has not yet been configured. Since Twisted is an event, you must make sure to use this code in response to an event that says the connection has been set up.

You can do this by activating the callback when the protocol is built instead of just setting the attribute. Twisted really has a factory helper that already does something like this:

 from twisted.internet.protocol import ClientCreator cc = ClientCreator(reactor, MyProtocol) whenConnected = cc.connectTCP(host, port) # Or the equivalent with endpoints # from twisted.internet.endpoints import TCP4ClientEndpoint # from twisted.internet.protocol import ClientFactory # endpoint = TCP4ClientEndpoint(reactor, host, port) # factory = ClientFactory() # factory.protocol = MyProtocol # whenConnected = endpoint.connect(factory) def cbConnected(connectedProtocol): connectedProtocol.send_message(...) def ebConnectError(reason): # Connection attempt failed, perhaps retry ... whenConnected.addCallbacks(cbConnected, ebConnectError) 

You can also save the link to connectedProtocol in the cbConnected callback cbConnected that you can continue to use it later. You can also start any other operations that you want to use the connected protocol in cbConnected so that they do not try to use the connection before it is really available.

+10
source

All Articles