2016-11-08 2 views
1

Я общаюсь с аппаратным обеспечением, которое имеет только рудиментарный API, поддерживающий основные вызовы API.Как читать только данные из сокета при необходимости

К сожалению, некоторые из API вызывает незаконный ответ, а некоторые нет. Я хочу прочитать ответ, когда он есть, или просто ничего не делать, когда его нет.

Вот код, я использую:

def send_message(self, message, host): 
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 
     s.connect((host, self.PORT)) 
     s.send(bytes(message, 'ascii')) 
     data = s.recv(1024) 
     print(data) 

К сожалению, это связывает весь процесс, когда не получено данных. Я хочу читать данные только тогда, когда есть реальный ответ. Есть ли способ сделать это с помощью стандартной библиотеки Python?

+0

может зависеть от вашей ОС, но, возможно, модуль 'select' будет работать на вас? – thebjorn

ответ

2

Во-первых, если у вас есть контроль над целевым API, я бы предложил реализовать ответ для каждого сообщения. Ответ ACK (подтверждение) для каждого отправленного сообщения сделает ваш API более надежным и полностью устранит эту проблему.

Если это не вариант, то я хотел бы создать классы для различных типов сообщений:

class Message(object): 
    def __init__(self, msg): 
     self.msg = msg 

class MessageWReply(Message): 
    await_reply = True 

class MessageNoReply(Message): 
    await_reply = False 

Создать все ваши классы сообщений, а затем использовать их, как это:

def send_message(self, message, host): 
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 
     s.connect((host, self.PORT)) 
     s.send(bytes(message, 'ascii')) 

     if message.await_reply: 
      data = s.recv(1024) 
      print(data) 

В качестве альтернативы , если вы не хотите накладных расходов на создание всех классов, вы можете использовать словарь для сопоставления сообщений с правильным действием:

messages = { 
    'message with reply 1': True, # wait for reply 
    'message with reply 2': True, 
    'message with reply 2': True, 
    'message without reply 1': False, # don't wait for reply 
    'message without reply 2': False 
} 

Тогда это сделать:

def send_message(self, message, host): 
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 
     s.connect((host, self.PORT)) 
     s.send(bytes(message, 'ascii')) 

     if messages[message]: 
      data = s.recv(1024) 
      print(data) 

Второй способ имеет чистую инициализацию (менее шаблонный код), но немного менее ясна. Для кого-то, не знакомого с кодом, неясно, что на самом деле означает значение, хранящееся в messages[message], а message.await_reply - кристально чистое. Что-то вроде named tuples может быть хорошим компромиссом - вы можете инициализировать все в одной структуре данных, все еще используя явные поля для ясности.

0

Я работал с аналогичными программами, и в одном я использовал if message, message, в этом случае это строка, полученная из сокета. Вот мой код:

while True: 
readbuffer = readbuffer + s.recv(1024) 
temp = string.split(readbuffer, "\n") 
readbuffer = temp.pop() 

for line in temp: 
    try: 
     user = getUser(line) 
     message = getMessage(line) 
    except IndexError: 
     print "Nothing to receive from the server!" 

    if message: 
     #responses here 
2

Если вы не знаете, должен ли ответ следовать априорно, отправляя сообщение, тогда вы обречены. Позвольте мне повторить: если API либо ответит, либо нет, и вы не знаете, когда закончится игра. Это потому, что вопрос «должен ли я ждать ответа?» является неопровержимым. И это не связано с Python вообще, переключение языка не поможет решить это. Но такой API был бы очень плохим. Многие полезные инструменты (например, таймауты, параллельный доступ) были бы невозможны (или чрезвычайно сложно) реализовать.

С другой стороны, если вы знаете, когда API должен отвечать, а когда нет, то это так же просто, как создание двух функций: один с recv и один без. И используйте их надлежащим образом. Поэтому основная работа, которую вы должны сделать, - это различать уведомления (которые не требуют ответа) и запросы (которые требуют ответа). Вот и все.

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