Cómo enviar datos con protocolo trenzado vía fábrica.

Estoy escribiendo un cliente que implementa un protocolo personalizado y tengo una fábrica para él. Mi problema es el siguiente: mi cliente tiene comunicación bidireccional y, a veces, quiero decirle “enviar esta información”. Pero todo lo que tengo es el objeto de fábrica:

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) 

Así que creo una fábrica y tengo un objeto de fábrica, no hago el objeto de protocolo. Cuando se llama a send_message anterior, aparece un error porque self.protocol es solo una clase, no un objeto.

¿Cómo puedo hacer esto? ¿Debo también exponer el protocolo para la conexión además de la fábrica?

Gracias

    Tienes acceso a todos los objetos que quieras. La fábrica es responsable de crear instancias de protocolo, por lo que si desea mantener la instancia de protocolo en un lugar donde la fábrica puede usarla, anule buildProtocol y guarde la instancia:

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

    Sin embargo, este enfoque carece de una característica importante. No hace que sea fácil saber cuándo se ha llamado a buildProtocol cuando se ha connectedProtocol . Si intentas usar este atributo ingenuamente:

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

    El código fallará con un AttributeError porque la conexión aún no se ha configurado realmente. Dado que Twisted está dirigido a eventos, debe asegurarse de usar este código respondiendo a un evento que indique que se ha configurado la conexión.

    Puede hacer esto activando una callback cuando se construye el protocolo en lugar de simplemente establecer un atributo. Twisted en realidad tiene una fábrica de ayudantes que ya hace algo como esto:

     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) 

    También puede guardar la referencia a connectedProtocol en la cbConnected llamada de cbConnected para que pueda seguir usándola más adelante. También puede iniciar cualquier otra operación que desee usar el protocolo conectado en cbConnected , para que no intenten usar la conexión antes de que esté realmente disponible.