Разбор сообщения переменной длины - PullRequest
1 голос
/ 23 июня 2009

Я реализую протокол BitTorent с использованием Java через эту спецификацию . В разделе сообщений все сообщения имеют фиксированную длину, кроме 2 из них; для одного из них это единственное переменное сообщение после рукопожатия, поэтому я могу проверить другие и предположить, что это частичное сообщение, когда другие сообщения не встречались. Но для следующего сообщения

bitfield: <len=0001+X><id=5><bitfield>

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

Сообщение битового поля имеет переменную длину, где X - длина битового поля. Полезная нагрузка - это битовое поле, представляющее фрагменты, которые были успешно загружены. Старший бит в первом байте соответствует индексу 0 фрагмента. Биты, которые очищены, указывают на отсутствующий фрагмент, а установленные биты указывают действительный и доступный фрагмент. Запасные биты в конце установлены в ноль.

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

Я не могу придумать способ разобрать его, если не знаю длины; Как я должен найти идентификатор в потоке байтов?

Редактировать: В полезной нагрузке сообщения битового поля 0 или 1 для каждого фрагмента в торрент-файле, длина сообщения будет меняться в зависимости от размера торрент-содержимого. Поэтому я не думаю, что могу предположить, что количество частей всегда будет соответствовать 5-байтовому числу.

Ответы [ 4 ]

3 голосов
/ 23 июня 2009

Поле id всегда будет 5-м байтом сообщения после четырех байтов поля len. Вы можете сделать что-то вроде следующего:

DataInputStream stream;

// ...

int    length  = stream.readInt();
byte   id      = stream.readByte();
byte[] payload = new byte[length - 1];

stream.readFully(payload);

На самом деле это должно работать для любого сообщения, поскольку все они имеют одинаковый заголовок len + id.

Редактировать:"Так что я не думаю, что могу предположить, что количество частей всегда будет соответствовать 5-байтовому числу."

Поле длиной в четыре байта может обрабатывать до 2 ^ 32-1 байтов в полезной нагрузке и с 8 битами на байт, что дает вам место для 34 359 738 360 штук. Этого должно быть много! : -)

2 голосов
/ 23 июня 2009

Ранее в спецификации, на которую вы ссылались, я читал: ' Префикс длины - это четырехбайтовое значение с прямым порядком байтов. Я прочитал это как: прочитайте следующие четыре байта, преобразовайте их в целое число, и это должно быть вашей длиной. Если вы не знакомы с процессом преобразования байтов в int, я использовал что-то похожее на this .

2 голосов
/ 23 июня 2009

Я не могу придумать способ разобрать его если я не знаю длину;

Судя по описанию, длина указана в первых 4 байтах сообщения.

как мне найти идентификатор в поток байтов?

Похоже, что id - это 5-й байт в каждом сообщении сразу после поля длины. Так что вам просто нужно посмотреть первые 5 байтов после того, как вы закончили анализ предыдущего сообщения.

1 голос
/ 23 июня 2009

Я не читал спецификацию подробно, но без явного знания длины поля переменной длины или какого-либо ограничителя завершения, я не вижу, как вы можете обработать его. Возможно, bitfield=<len=0001+X> не означает, что вам будут сообщать о (переменной) длине вперед ?

...