Битторрент и сокеты: как обрабатывать несколько сообщений? - PullRequest
0 голосов
/ 21 апреля 2020

Я пишу bittorrent-клиент в python и использую al oop для постоянного чтения сообщений из одноранговых сокетов с помощью recv ().

Когда я запускаю свою программу, я смотрю в wireshark, чтобы увидеть, какие битторрент-сообщения я получаю. Довольно просто определить, какое сообщение вы получили из первых 5 байтов сообщения, поскольку там указаны длина и идентификатор сообщения.

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

Я попытался решить эту проблему, написав такой метод:

    def handleMultiple(self, message, peer):
        total_length = len(message)
        parsed = 0
        while parsed < total_length:
            m_len, m_id = struct.unpack(">IB", message[parsed:parsed + 5])
            m_total = m_len + 4
            print(m_len, total_length, parsed, m_id, peer.made_handshake, peer.ip)

            self.handleMessage(message[parsed:m_total + parsed], peer)
            parsed += m_total

Функция просто разбивает полученные байты на составляющие сообщения и передает их обработчику сообщений, который знает как бороться с отдельными сообщениями.

Проблема в том, что когда я распечатывал префикс длины и идентификатор сообщения из сообщения, полученного с помощью recv (), иногда это выглядит как просто числа мусора.

Это действительно мой первый опыт экспериментирования с сокетами, поэтому мне не хватает интуиции, чтобы знать, что я действительно получаю при вызове recv (). Должен ли я просто вызвать receive для первых 5 байтов данных, которые я получу, затем выполнить некоторую проверку, чтобы убедиться в правильности длины и идентификатора, а затем вызвать recv () для остальной части сообщения?

Как мне go обрабатывать несколько входящих сообщений одновременно?

Редактировать: Я хотел предоставить некоторые изображения результатов, которые я вижу, чтобы посмотреть, сможет ли кто-нибудь помочь определить проблема у меня Вот изображение битрорент-сообщений, которые я получаю: Wireshark Capture

Вот соответствующий вывод журнала: столбцы должны иметь длину сообщения + 4, общую длину сообщения, идентификатор сообщения и IP от отправителя:

enter image description here

Как я вижу, префикс длины для первых сообщений (те, которые являются отправленными несколькими сообщениями) для меня в то время) слишком велики. Пятое сообщение, которое я получил от 95.211.212.26, является правильно сформированным сообщением битового поля.

Еще одна вещь, которую я заметил, состоит в том, что предполагаемый идентификатор сообщения для каждого из сообщений с несколькими сообщениями равен 255. Также, учитывая, что общая длина сообщение о битовом поле для данного заданного торрента равно 126, общая длина (303, 328, 325) немыслима для сообщений битового поля, за которыми следуют несколько сообщений.

1 Ответ

0 голосов
/ 21 апреля 2020

Хорошо, так что мне удалось выяснить, где я иду не так. Я читал из сокета, предполагая, что мое сообщение будет там в полном объеме. На самом деле я читал первоначальный фрагмент сообщения, а позже читал середину сообщения. 255 значений, которые я видел, были не идентификаторами сообщений, а фактически серединой битового поля партнера (0xff).

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

...