Вопрос 1
Придерживаясь простых методов, если вы используете поточный ввод-вывод, используйте DataInputStream и DataOutputStream при записи примитивных типов (например, byte, int, long и т. д.):
Socket s; // assume this is already connected
DataOutputStream out = new DataOutputStream( s.getOutputStream );
out.writeByte( 1 );
out.writeInt( 0 );
out.flush(); // optional
Если вы используете неблокирующий ввод-вывод (например, классы из пакета java.nio), используйте ByteBuffer:
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
(Обратите внимание, что обычно вы передаете блоки, которые представляют собой фрагменты частей, по сети. Я не буду говорить об этом здесь :) )
При отправке/получении частей лучше всего думать о файлах (или файлах) как о непрерывных, как вы сказали. Файл .torrent содержит информацию о границах файла в информационном словаре. В многофайловом случае каждый файл имеет путь и длину; однофайловый случай имеет необязательное имя и длину. Поскольку вы знаете размер фрагмента, количество фрагментов и общую длину контента (все из файла .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. И так далее...
Могу поспорить, что теперь вы можете понять, как превратить этот файл .downloading в «настоящий» контент внутри вашего торрента.
Вопрос 3
Участвуя в рое BitTorrent, вы одновременно загружаете и скачиваете фрагменты на несколько пиров и с них. Подумайте об этом на секунду. В то же время, когда вы запрашиваете кусок у какого-то пира, другой пир может делать то же самое у вас. Как вы уже указали, это сильно отличается от семантики HTTP. Итак, если говорить непосредственно о вашем вопросе, другие сверстники будут запрашивать у вас интересующие их данные. :)
Просто чтобы удостовериться, прежде чем запрашивать фрагмент a у пира, убедитесь, что у пира есть нужный вам фрагмент (ознакомьтесь с битовое поле и иметь сообщения), и вы соблюдали надлежащее удушье/заинтересованность поведение. Учитывая это, то, что вы обычно хотите сделать, это запросить данные из вашего списка известных пиров (о которых вам сообщил трекер или DHT) в наиболее редком порядке. Спецификация говорит об этом, и здесь есть МНОГО оптимизаций и соображений вежливости. (Например, поведение «око за око».) Вы могли заметить, что spec не означает многое из этого. Это потому, что в этой части реализации кроется большая часть секретного соуса клиентов BitTorrent. :)
Я надеюсь, что это поможет вам немного!
person
JLR
schedule
22.06.2009