перепутанная функция обратного вызова

1

Я работаю над скрученным учебником, чтобы узнать больше python, и, похоже, я столкнулся с дорожным блоком. Функция doRead() ниже - это "обратный вызов" реактора. Я не понимаю, как работает эта часть.

То, как я читаю код, состоит в том, что если bytes += self.sock.recv(1024) вызвал бы блок, то он достигнет следующей части кода:

if e.args[0] == errno.EWOULDBLOCK:
    break

Затем он продолжал бы следующее:

if not bytes:
    print 'Task %d finished' % self.task_num
    return main.CONNECTION_DONE
else:
    msg = 'Task %d: got %d bytes of poetry from %s'
    print  msg % (self.task_num, len(bytes), self.format_addr())

Сложная часть для меня заключается в том, что если она заблокирована, то переменная байтов ничего бы не содержала и напечатала бы "финиш", но это не так. Или, по крайней мере, это напечатало бы что-то вроде "got 0 bytes", но это также не так. Мне кажется, что когда код встречает блок из вызова recv, он полностью пропускает эту часть. Может кто-нибудь объяснить, почему это происходит?

Результат выглядит примерно так:

Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 3: got 3 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000

Это целая функция:

def doRead(self):
    bytes = ''

    while True:
        try:
            bytes += self.sock.recv(1024)
            if not bytes:
                break
        except socket.error, e: # I don't understand this part
            if e.args[0] == errno.EWOULDBLOCK:
                break
            return main.CONNECTION_LOST

    if not bytes:
        print 'Task %d finished' % self.task_num
        return main.CONNECTION_DONE
    else:
        msg = 'Task %d: got %d bytes of poetry from %s'
        print  msg % (self.task_num, len(bytes), self.format_addr())

    self.poem += bytes

Весь модуль вставляется здесь: http://pastebin.com/bUnXgbCA

  • 0
    Я не могу воспроизвести ваши результаты. Когда я подключаю код к серверу, когда сервер отключается, печатается «готово». Вы уверены, что сервер, к которому вы подключаетесь, фактически закрывает соединение? Кроме того, вы знаете, что это приложение лучше реализовать в виде протокола, а не IReadDescriptor, верно?
Теги:
twisted

1 ответ

2
Лучший ответ

Дело в том, что метод doRead вызывается только тогда, когда сокет "готов к чтению": либо он имеет некоторые данные на нем, либо все это делается (а затем чтение вернет 0). Таким образом, решение вашей проблемы не может быть в функции doRead - все это в коде, вызывающем его только при необходимости.

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

  • 0
    Спасибо, что ответили, Алекс. Я не пытаюсь решить какую-либо проблему, просто пытаюсь понять, как это работает. Я до сих пор не уверен, что происходит сразу после оператора break в блоке exc, поскольку кажется, что он вообще не достигает блока «if not bytes:».
  • 0
    @ Джозеф, поэтому он никогда не вызывается (в ваших экспериментах) при ошибке сокета (которая возвращает возвращаемое условие), но только когда его коллега "просто зависает" (соединение потеряно).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню