2016-01-29 2 views
1

Я пытаюсь отслеживать исключение тайны из socket.recv(), у которого нет сообщения, чтобы дать представление о том, откуда он или почему. Это на Windows 7, Python 2.7.Исключение без информации из блокирующего сокета в Python

создать блокирующий сокет так:

self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
self.client.settimeout(5) 

подключить к части оборудования, потоки данных из. Я никогда ничего не посылаю через этот сокет, я получаю только. Поэтому я вращаюсь в цикле вызова select:

while(True): 
    # Process commands from the GUI. These can include requests to 
    # connect, disconnect, or quit 
    quitting = self.processCmds() 
    if quitting == True: 
     print 'exiting' 
     return 
    try: 
     rlist, wlist, errlist = select.select([self.client], [], [self.client], 5) 
     if self.client in errlist: 
      self.reconnect() 
      continue 
     elif self.client in rlist: 
      # We have a message. 
      msg = recvall(self.client, MESSAGE_LENGTH) 
       if msg == None: 
        self.reconnect() 
        continue 

Пока что так хорошо. rcvall() крутится в цикле так, как и следовало ожидать, пытаясь прочитать запрошенное количество байт:

def recvall(conn, count): 
    buf = b'' 
    numIterations = 0 
    while count: 
     try: 
      recvString = conn.recv(count) 
     except: 
      # OH NO SOMETHING BAD HAPPENED! 
      e = sys.exc_info()[0] 
      return None 
     if not recvString: 
      # the socket has been closed by the remote end 
      return None 
     if (len(recvString) > 0): 
      buf = buf + recvString 
      count = count - len(recvString) 
     else: 
      # If the other guy has sent no bytes, don't wait forever 
      numIterations += 1 
      if numIterations > 100: 
       return None 
    return buf 

Так что, если что-то пойдет не так, recvall() не возвращает None, который сообщает абоненту, чтобы закрыть существующий подключиться и открыть новый.

Это работает красиво около 8 часов или около того, но затем я вижу поток попыток повторного подключения в моем журнале, но ничего не получается. После некоторой охоты и клевания с контрольными точками я узнаю, что мы делаем исключение в rcvall(), где комментарий OH NO SOMETHING BAD HAPPENED! является. Но когда я пытаюсь проверить объект исключения в отладчике, его элемент сообщения - «Нет». На самом деле, все его члены - Ники, поэтому нет никакого понятия о том, кто его поднимает или почему.

Есть несколько странных вещей об этом. Исключение происходит ПОСЛЕ того, как select() уже сказал мне, что сокет является безошибочным и содержит данные. Может ли что-то пойти не так между вызовом select() и вызовом recvall()? Это возможно, но вряд ли кажется вероятным.

второй, кто-нибудь видел такое странное исключение, исходящее из socket.recv? Любой ключ, где его искать?

+0

Исключение может иметь полезную информацию, неясно, распечатываете ли вы ее. Это было бы первым делом. Во-вторых, если клиент отключается, вы можете обнаружить его только при попытке чтения/записи. Это странность API-интерфейса сокета UNIX TCP/IP, но выбор не скажет вам об этом. См. Http://stackoverflow.com/questions/283375/detecting-tcp-client-disconnect – rts1

+0

Хорошее предложение. Я думаю, что моя следующая яркая идея - удалить catch для этого исключения и запустить его без IDE. Возможно, трассировка командной строки будет более познавательной, чем показывает IDE. Иногда Visual Studio + PTVS смешно рассказывать вам всю историю, когда происходит исключение. Я подозреваю, что что-то не так на другом конце, и, возможно, больше информации. об этом исключении скажут мне, что это такое. – user2623722

ответ

0

Похоже, что удаленный конец принудительно закрывает соединение, но Visual Studio + PVTS смешно показывать всю информацию об исключении. Кроме того, по-видимому, в Windows вы уведомлены о другом конце, закрывающем соединение через исключение, вместо recv(), возвращающего None, как говорят документы.

Я отключил обработчик исключений и бежал без IDE, чтобы позволить Python распечатать трассировку. Иногда Visual Studio смешно рассказывать вам всю историю с исключениями. Это то, что я получил:

Exception in thread Thread-2: 
Traceback (most recent call last): 
    File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner 
    self.run() 
    File "../shared\retrieveMessage.py", line 184, in run 
    msgLength = recvall(self.client, 2) 
    File "../shared\retrieveMessage.py", line 52, in recvall 
    recvString = conn.recv(count) 
error: [Errno 10054] An existing connection was forcibly closed by the remote host 

Таким образом, похоже, что другая сторона плохо себя ведет.

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