Разбор сообщения переменной длины
-
06-07-2019 - |
Вопрос
Я реализую протокол BitTorent с использованием Java с помощью этой спецификации . В разделе сообщений все сообщения имеют фиксированную длину, кроме 2 из них; для одного из них это единственное переменное сообщение после рукопожатия, поэтому я могу проверить другие и предположить, что это частичное сообщение, когда другие сообщения не встречались. Но для следующего сообщения
bitfield: <len=0001+X><id=5><bitfield>
Сообщение битового поля может быть отправлено только сразу после завершения последовательности квитирования и до отправки любых других сообщений. Это необязательно, и его не нужно отправлять, если у клиента нет частей.
Сообщение битового поля имеет переменную длину, где X - длина битового поля. Полезная нагрузка - это битовое поле, представляющее фрагменты, которые были успешно загружены. Старший бит в первом байте соответствует индексу 0 фрагмента. Биты, которые очищены, указывают на отсутствующий фрагмент, а установленные биты указывают действительный и доступный фрагмент. Запасные биты в конце установлены на ноль.
Битовое поле неправильной длины считается ошибкой. Клиенты должны разорвать соединение, если они получают битовые поля, которые имеют неправильный размер, или если битовое поле имеет какой-либо из установленных резервных битов. Р>
Я не могу придумать способ разобрать его, если не знаю длины; Как я должен найти идентификатор в потоке байтов?
Редактировать: В полезной нагрузке сообщения битового поля 0 или 1 для каждого фрагмента в торрент-файле, длина сообщения будет меняться в зависимости от размера содержимого торрента. Поэтому я не думаю, что могу предположить, что количество частей всегда будет соответствовать 5-байтовому числу.
Решение
Поле id
всегда будет 5-м байтом сообщения после четырех байтов для поля len
. Вы можете сделать что-то вроде следующего:
DataInputStream stream;
// ...
int length = stream.readInt();
byte id = stream.readByte();
byte[] payload = new byte[length - 1];
stream.readFully(payload);
На самом деле это должно работать для любого сообщения, поскольку все они имеют одинаковый заголовок <=> + <=>.
Edit: " поэтому я не думаю, что могу предположить, что количество частей всегда будет соответствовать 5-байтовому числу. "
Поле длиной в четыре байта может обрабатывать до 2 ^ 32-1 байтов в полезной нагрузке и с 8 битами на байт, что дает вам место для 34 359 738 360 штук. Этого должно быть много! : -)
Другие советы
Я не могу придумать способ разобрать его если я не знаю длину;
Судя по описанию, длина указана в первых 4 байтах сообщения.
как я должен найти идентификатор в поток байтов?
Похоже, что идентификатор является 5-м байтом в каждом сообщении, сразу после поля длины. Так что вам просто нужно посмотреть первые 5 байтов после того, как вы закончили анализ предыдущего сообщения.
Ранее в спецификации, на которую вы ссылались, я читал: « Префикс длины - это четырехбайтовое значение с прямым порядком байтов. ». Я прочитал это как: прочитайте следующие четыре байта, преобразовайте их в целое число, и это должно быть вашей длиной. Если вы не знакомы с процессом преобразования байтов в int, я использовал что-то похожее на это . Р>
Я не читал спецификацию подробно, но без явного знания длины поля переменной длины или какого-либо ограничителя завершения, я не вижу, как вы можете обработать его. Возможно, bitfield=<len=0001+X>
не означает, что вам сообщат о (переменной) длине заранее ?