Вопрос

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

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

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

<Ол>
  • Это правильный способ сделать это в Python (т.е. действительно ли это так просто)?
  • Любые советы / хитрости / полезные ресурсы (кроме справочной документации), касающиеся буферов / 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 . Первый вопрос является основным (ответ основан на этом), но любые другие идеи / советы приветствуются. Спасибо.

    Это было полезно?

    Решение

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

    Другие советы

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top