Refatoração para uma torcida de cliente tcp de bloqueio de código existente
-
20-12-2019 - |
Pergunta
Eu tenho um programa python que usa atualmente um cliente de tcp/ip módulo escrevi para receber dados de um servidor de streaming.O servidor saídas de linhas de dados.
Meu cliente TCP classe é bastante primitivo e eu quero refatorar para usar uma torcida ReconnectingClientFactory.
O principal programa obtém dados a partir de um readLines função no meu Cliente de TCP que 'produz' as linhas como eles são recebidos.
O cliente de TCP método é acessado por:
for msg_buffer in self.myTcpClient.readLines():
do some stuff with the data in msg_buffer
No meu Cliente de TCP o método readLines em essência parece:
while True:
newLine = self.sock.recv(self.buffer_size)
yield newLine
Quando eu implementar a torcida cliente eu vou querer de alguma forma para que se comporte como um iterador e dados de produção.Eu suponho que eu gostaria de fazer algo no protocolo dataReceived método.
Eu estou perdido tentando descobrir como isso funciona.Parece-me que a torcida diferidos são destinados para este tipo de uso, mas eu não consigo descobrir como usar um adiada para o meu propósito (se minha suposição sobre diferido é correto).
Em um mundo perfeito, a torcida do cliente produziria as linhas como receber uma chamada semelhante para o presente método iria fazer o trabalho.i.e.
class GetData(protocol):
def dataReceived(self, data):
yield data
Mas eu acho que é uma simplificação excessiva.
Em resumo, o que eu estou tentando fazer é implementar uma torcida reconectar TCP cliente que se comporta algo como o meu método readLines e podem ser acessados com mais ou menos assim:
for msg_buffer in self.twistedTcpClient.readLines():
Qualquer ponteiros vai ser muito apreciada
ATUALIZAÇÃO:Eu só tropeçou em 'Crochê' para a torcida.À primeira vista, Crochê parece ter sido concebido exatamente para o tipo de modelo que eu preciso...Vou relatar de volta depois de alguns testes
Solução
A Torcida maneira de fazer isso seria escrever um Protocolo.Em vez de fazer:
for line in self.twistedTcpClient.readLines():
process_line(line) ...
Você gostaria de escrever o seu Protocolo (talvez por uma subclassificação twisted.protocols.basic.LineReceiver
):
class MyProtocol(LineReceiver):
...
def lineReceived(self, line):
process_line(line) ...
Você quer refatorar seu código para usar o lineReceived
de retorno de chamada em vez de ter uma iteração do loop.
O que você tem escrito:
for line in self.twistedTcpClient.readLines():
process_line(line) ...
é problemático, uma vez que Torcida é assíncrona.Não há nenhuma maneira para Torcida para dar a volta a fazer qualquer outra coisa enquanto espera para twistedTcpClient.readLines()
o método.
Eu sugiro escrever um protocolo, mas se você realmente insiste em ter este iterador padrão, então você pode ser capaz de fazer isso:
@inlineCallbacks
def my_func():
while True:
try:
line = yield self.twistedTcpClient.getNextLine()
except StopIteration:
break
process_line(line) ...
Agora, o mais complicado é fazer com que twistedTcpClient
retorno Deferreds
para cada chamada para getNextLine().Talvez algo como isto:
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 é apenas um exemplo que ilustra a idéia, o que você teria para estendê-lo a lidar com os detalhes.)