2009-11-26 2 views
1

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

Данные, перемещаемые с сервера -> клиент, кодируются в кодировке 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. Первый вопрос является основным (на это основан ответ), но любые другие идеи/советы оценены. Благодарю.

+0

Мне было любопытно, что такое ByteUtils в вашем коде, где я googled «python ByteUtils» ... и google дал мне эту тему - через 15 минут после ее создания! Thats впечатляет :) – truppo

ответ

6

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

Я знаю, что сервер отправляет через «строки», которые заканчиваются CRLF, хотя, я уверен, что в какой-то момент времени буфер будет прекращен (если на сервере не произойдет что-то не так, отправьте это в некоторую форму переполнения буфера за считанные минуты). Я читал о Twisted, но это еще не для Python 3, но AFAIK, и, вероятно, это будет излишним для этого. – tmbrggmn

+0

Вы по-прежнему рискуете получить несколько строк вместо одного с вашим текущим кодом. – truppo

+0

yay! +1 к скрученному! – nosklo

6

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

+1

Сначала я попробовал асинчат, но столкнулся с небольшими проблемами, которые я не мог решить сразу (что-то делать с буфером), поэтому я вернулся к asyncore. – tmbrggmn

+3

+1 при использовании asyncore/asynchat вместо Twisted для таких простых задач. –

+0

@Denis: Я думаю, что скрученный пример выше ** очень простой ** и простой, не так ли? – nosklo

Смежные вопросы