Одноранговый проводной протокол Bittorrent, реализуемый на Java

StackOverflow https://stackoverflow.com/questions/1023816

Вопрос

У меня есть пара вопросов относительно однорангового проводного протокола Bittorrent.Я пытаюсь реализовать это на Java, используя эта спецификация.

В разделе протокола Peer Wire говорится, что все целые числа представляют собой четырехбайтовые значения с большим конечным порядком.AFAIK java использует большой порядковый номер.Означает ли это сказать, хочу ли я отправить прерывающее сообщение

подавиться:<len=0001><id=0>

Должен ли я просто записать в sokcet 1, за которым следует 0?

Что касается моего второго вопроса.запрашивая фрагмент, рассматриваю ли я несколько файлов как один большой непрерывный файл?или мыслите отдельными файлами?потому что длина фрагмента не будет совпадать с файлами, поэтому один индекс может содержать как конец одного файла, так и начало другого?

Что касается моего последнего вопроса, когда я открываю соединение с одноранговым узлом и отправляю свое рукопожатие, я просто продолжаю запрашивать фрагменты или запрашиваю, а затем жду некоторое время, чтобы посмотреть, запросит ли он что-нибудь от нас?как происходит разговор?В основном я занимался сетевым программированием типа http, где я запрашиваю что-то и жду ответа.но если я продолжу запрашивать фрагменты, как я собираюсь отправлять фрагменты?

Это было полезно?

Решение

Вопрос 1

Придерживаясь простых методов, если вы используете потоковый ввод-вывод, то используйте Поток ввода данных и Поток вывода данных при написании примитивных типов (например, байт, инт, длинный, и т.д.):

Socket s; // assume this is already connected
DataOutputStream out = new DataOutputStream( s.getOutputStream );
out.writeByte( 1 );
out.writeInt( 0 );
out.flush(); // optional

Если вы используете неблокирующий ввод-вывод (напримерклассы из пакета java.nio), затем используйте Байтбуфер s:

Socket s; // assume this is already connected
SocketChannel = s.getChannel();
ByteBuffer buf = ByteBuffer.allocate(8); // two 4-byte integers
buf.put( 1 ).putInt( 0 );
buf.flip();
c.write( buf ); // assuming channel is writable :)

Каждый из этих методов позаботится о проблемах с упорядочением байтов от вашего имени.

Вопрос 2

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

При отправке / получении фрагментов лучше всего думать о файлах (или file) как о непрерывных, как вы сказали.Файл .torrent содержит информацию о границах файла в справочнике info.В дело с несколькими файлами, каждый файл имеет путь и длину;в дело в одном файле имеет необязательное имя и длину.Поскольку вы знаете размер фрагмента, количество фрагментов и общую длину содержимого (все из файла .torrent), вы можете размещать фрагменты "в нужном месте" по мере их получения.

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

a/b/file1.txt [100 bytes]
a/b/file2.txt [200 bytes]

piece size (pz) = 50 bytes
total size (tz) = 100+200 = 300 bytes
number pieces (np) = 300/50 = 6
file = my_torrent.downloading

Предположим, мы нумеруем фрагменты и смещения байтов, начиная с нуля.Допустим, вы получили всю часть 1.С каким (начальным) смещением в байтах это происходит в my_torrent.downloading?Это происходит при (1 * pz) = (1*50) = 50.Куда девается часть 0?При (0*pz) = (0*50) = 0.И так далее...

Держу пари, что теперь вы можете понять, как это превратить.загружаемый файл превращается в "реальный" контент внутри вашего торрента.

Вопрос 3

Участвуя в BitTorrent swarm, вы загружаете фрагменты на несколько одноранговых узлов и с них одновременно .Подумайте об этом на секунду.В то же время, когда вы запрашиваете фрагмент у какого-то однорангового узла, другой одноранговый узел может делать то же самое от вас.Сильно отличается от семантики HTTP, как вы уже указывали.Итак, чтобы ответить непосредственно на ваш вопрос, другие коллеги запросят у вас интересующие их данные.:)

Просто чтобы убедиться, прежде чем запрашивать фрагмент a у однорангового узла, убедитесь, что у этого однорангового узла есть нужный вам фрагмент (ознакомьтесь с битовое поле и иметь сообщения) и вы соблюдали надлежащие задыхающийся / заинтересованный поведение.Учитывая это, то, что вы обычно хотите сделать, это запросить данные из вашего списка известных одноранговых узлов (о которых вам сообщил трекер или DHT) в самый редкий первый порядок.В спецификации говорится об этом, и здесь есть МНОГО оптимизаций и соображений вежливости.(Например, поведение "Око за око".) Вы могли бы заметить, что спецификация не очень-то это понятно.Это потому, что большая часть секретного соуса клиентов BitTorrent заключается в этой части реализации.:)

Я надеюсь, что это вам немного поможет!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top