2009-06-22 4 views
1

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

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

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

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

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

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

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

+0

Пунктуация, пожалуйста! – JesperE

+0

Эй, у него есть двоеточие! – skaffman

+0

Я положил эту точку с запятой. : P –

ответ

3

Поле id всегда будет пятым байтом сообщения после четырех байтов для поля 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 штук. Этого должно быть много! :-)

1

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

2

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

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

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

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

2

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

+0

От того, что я понимаю, читает спецификацию, которая верна для всех сообщений, но битполит и кусок. По причинам, которые я добавил к вопросу. –

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