Pregunta

Tengo un programa Python que actualmente usa un módulo de cliente tcp/ip que escribí para recibir datos de un servidor de transmisión.El servidor genera líneas de datos.

Mi clase de cliente TCP es bastante primitiva y quiero refactorizarla para usar una ReconnectingClientFactory retorcida.

Actualmente, el programa principal obtiene datos de una función readLines en mi cliente TCP que "produce" las líneas a medida que se reciben.

Al método del cliente TCP se accede mediante:

for msg_buffer in self.myTcpClient.readLines():
    do some stuff with the data in msg_buffer

En mi cliente TCP, el método readLines en esencia se ve así:

while True:
    newLine = self.sock.recv(self.buffer_size)
    yield newLine

Cuando implemente el cliente retorcido, querré alguna forma de que se comporte como un iterador y produzca datos.Supongo que haría algo en el método dataReceived del protocolo.

Estoy perdido tratando de descubrir cómo funciona esto.Me parece que los diferidos retorcidos están destinados a este tipo de uso, pero no sé cómo utilizarlos para mi propósito (si mi suposición sobre los diferidos es correcta).

En un mundo perfecto, el cliente retorcido entregaría las líneas tal como las recibió, por lo que una llamada similar al método actual haría el trabajo.es decir.

class GetData(protocol):
    def dataReceived(self, data):
        yield data

Pero creo que es una simplificación excesiva.

En resumen, lo que estoy tratando de hacer es implementar un cliente TCP de reconexión retorcido que se comporte de manera similar a mi método readLines y se pueda acceder a él más o menos como:

for msg_buffer in self.twistedTcpClient.readLines():

Cualquier consejo será muy apreciado.

ACTUALIZAR:Me topé con 'Crochet' para retorcido.A primera vista, Crochet parece haber sido diseñado exactamente para el tipo de modelo que necesito...Informaré después de algunas pruebas.

¿Fue útil?

Solución

La forma retorcida de hacer esto sería escribir un protocolo.En lugar de hacer:

for line in self.twistedTcpClient.readLines():
    process_line(line) ...

Escribirías tu protocolo (tal vez subclasificando un twisted.protocols.basic.LineReceiver):

class MyProtocol(LineReceiver):
    ...
    def lineReceived(self, line):
        process_line(line) ...

Quieres refactorizar tu código para usar el lineReceived devolución de llamada en lugar de tener un bucle iterado.

Lo que has escrito:

for line in self.twistedTcpClient.readLines():
    process_line(line) ...

es problemático ya que Twisted es asincrónico.No hay forma de que Twisted pueda hacer nada más mientras espera twistedTcpClient.readLines() método.

Sugiero escribir un protocolo, pero si realmente insiste en tener este patrón iterador, entonces podrá hacer esto:

@inlineCallbacks
def my_func():
    while True:
        try:
            line = yield self.twistedTcpClient.getNextLine()
        except StopIteration:
            break

        process_line(line) ...

Ahora lo complicado es hacer twistedTcpClient devolver Deferreds para cada llamada a getNextLine().Quizás algo como esto:

class MyProtocol(LineReceiver):
    ...
    def getNextLine(self):
        self.defer_given_out = Deferred()

    def lineReceived(self, line):
        self.defer_given_out.callback(line)

    def connectionLost(self):
        self.defer_given_out.errback(StopIteration())

(Este es sólo un ejemplo que ilustra la idea, tendrías que ampliarlo para manejar los detalles).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top