Pregunta

Soy nuevo en Python (aunque he estado programando en Java durante varios años) y estoy trabajando en una aplicación de red simple basada en socket (solo por diversión). La idea es que mi código se conecte a un punto final de TCP remoto y luego escuche los datos que se envíen del servidor al cliente y realice un análisis de esto.

Los datos que se envían desde el servidor - > el cliente es texto codificado en UTF-8, y cada línea está delimitada por CRLF ( \ x0D \ x0A ). Probablemente haya adivinado: la idea es que el cliente se conecte al servidor (hasta que el usuario lo cancele), y luego lea y analice las líneas a medida que ingresan.

Me las arreglé para hacer que esto funcionara, sin embargo, no estoy seguro de que lo esté haciendo de la manera correcta. Así que de ahí mis preguntas reales (código a seguir):

  1. ¿Es esta la forma correcta de hacerlo en Python (es decir, es realmente así de simple)?
  2. ¿Algún consejo / trucos / recursos útiles (aparte de la documentación de referencia) con respecto a los buffers / asyncore ?

Actualmente, los datos se están leyendo y almacenando en búfer de la siguiente manera:

def handle_read(self):
    self.ibuffer = b""

    while True:
        self.ibuffer += self.recv(self.buffer_size)
        if ByteUtils.ends_with_crlf(self.ibuffer):
            self.logger.debug("Got full line including CRLF")
            break
        else:
            self.logger.debug("Buffer not full yet (%s)", self.ibuffer)

    self.logger.debug("Filled up the buffer with line")
    print(str(self.ibuffer, encoding="UTF-8"))

La función ByteUtils.ends_with_crlf simplemente verifica los últimos dos bytes del búfer para \ x0D \ x0A . La primera pregunta es la principal (la respuesta se basa en esto), pero se agradece cualquier otra idea / consejo. Gracias.

¿Fue útil?

Solución

TCP es una secuencia, y no se le garantiza que su búfer no contendrá el final de un mensaje y el comienzo del siguiente. Por lo tanto, la comprobación de \ n \ r al final del búfer no funcionará como se espera en todas las situaciones. Tienes que comprobar cada byte en la secuencia.

Y, recomiendo encarecidamente que uses Twisted en lugar de asyncore. Algo como esto (de memoria, podría no funcionar fuera de la caja):

from twisted.internet import reactor, protocol
from twisted.protocols.basic import LineReceiver


class MyHandler(LineReceiver):

    def lineReceived(self, line):
        print "Got line:", line


f = protocol.ClientFactory()
f.protocol = MyHandler
reactor.connectTCP("127.0.0.1", 4711, f)
reactor.run()

Otros consejos

Es incluso más sencillo: consulte asynchat y su set_terminator (y otros datos útiles en ese módulo). Twisted son órdenes de magnitud más ricas y potentes, pero, para tareas suficientemente simples, asyncore y asynchat (que son diseñados para interactuar sin problemas) son, de hecho, muy fáciles de usar, ya que ha comenzado a observar.

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