Чтение буфера сокета с использованием asyncore - PullRequest
1 голос
/ 26 ноября 2009

Я новичок в Python (хотя я программирую на Java уже несколько лет), и я работаю над простым сетевым приложением на основе сокетов (просто для удовольствия). Идея состоит в том, что мой код подключается к удаленной конечной точке TCP, а затем прослушивает любые данные, передаваемые с сервера клиенту, и выполняет некоторый анализ этого.

Данные, передаваемые с сервера -> клиента, представляют собой текст в кодировке UTF-8, а каждая строка отделяется CRLF (\x0D\x0A). Вы, наверное, догадались: идея в том, что клиент подключается к серверу (пока пользователь не отменит его), а затем читает и анализирует строки по мере их поступления.

Мне удалось заставить это работать, однако я не уверен, что делаю это совершенно правильно. Поэтому отсюда и мои актуальные вопросы (код для подражания):

  1. Это правильный способ сделать это в Python (т.е. действительно ли это так просто)?
  2. Любые советы / рекомендации / полезные ресурсы (кроме справочной документации) относительно буферов / asyncore?

В настоящее время данные читаются и буферизуются следующим образом:

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"))

Функция ByteUtils.ends_with_crlf просто проверяет последние два байта буфера на \x0D\x0A. Первый вопрос является основным (ответ основан на этом), но любые другие идеи / советы приветствуются. Спасибо.

Ответы [ 2 ]

6 голосов
/ 26 ноября 2009

Это даже проще - посмотрите на asynchat и его set_terminator метод (и другие полезные лакомые кусочки в этом модуле). Twisted на несколько порядков богаче и мощнее, но для достаточно простых задач asyncore и asynchat (которые предназначены для плавного взаимодействия) действительно очень просты в использовании, как вы начали наблюдать.

6 голосов
/ 26 ноября 2009

TCP - это поток, и вам не гарантируется, что в вашем буфере не будет конца одного сообщения и начала следующего. Таким образом, проверка на наличие \ n \ r в конце буфера не будет работать должным образом во всех ситуациях. Вы должны проверить каждый байт в потоке.

И я настоятельно рекомендую вам использовать Twisted вместо asyncore. Примерно так (из памяти может не работать из коробки):

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()
...