Frage 1
Um bei einfachen Methoden zu bleiben, verwenden Sie bei der Verwendung von Stream-based I/O DataInputStream y DataOutputStream beim Schreiben primitiver Typen (z. B., Byte , int , lang , usw.):
Socket s; // assume this is already connected
DataOutputStream out = new DataOutputStream( s.getOutputStream );
out.writeByte( 1 );
out.writeInt( 0 );
out.flush(); // optional
Wenn Sie nicht-blockierende E/A verwenden (z. B. Klassen aus dem java.nio-Paket), verwenden Sie ByteBuffer 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 :)
Jede dieser Methoden wird sich in Ihrem Namen um die Bestellung von Byte kümmern.
Frage 2
(Beachten Sie, dass Sie normalerweise die Blöcke die Fragmente von Stücken sind, auf dem Draht. Ich werde das hier übergehen :) )
Beim Senden/Empfangen von Teilen ist es am besten, die Dateien (oder die Datei) als fortlaufend zu betrachten, wie Sie sagten. Die .torrent-Datei enthält Informationen über Dateigrenzen im Info-Wörterbuch. In der Mehraktenverfahren hat jede Datei einen Pfad und eine Länge; die Einzelaktenordner hat einen optionalen Namen und eine optionale Länge. Da Sie die Stückgröße, die Anzahl der Stücke und die Gesamtlänge des Inhalts kennen (alles aus der .torrent-Datei), können Sie die Stücke an der richtigen Stelle platzieren, wenn Sie sie erhalten.
Es ist einfach, eine einzelne Datei zu erstellen, die der Größe des Torrents entspricht. Wenn Sie ein Stück erhalten, schreiben Sie es an den richtigen Byte-Offset innerhalb dieser einzelnen Datei (manchmal auch ".downloading" genannt). Nehmen wir zum Beispiel einen Torrent, der aus zwei Dateien besteht:
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
Angenommen, wir nummerieren Stücke und Byte-Offsets beginnend mit Null. Angenommen, Sie erhalten das gesamte Stück 1. An welchem (Start-)Byte-Offset wird es in my_torrent.downloading abgelegt? Es beginnt bei (1*pz) = (1*50) = 50 . Wohin gehört das Stück 0? Bei (0*pz) = (0*50) = 0 . Und so weiter...
Ich wette, dass du jetzt herausfinden kannst, wie du diese .downloading-Datei in den "echten" Inhalt deines Torrents verwandelst.
Frage 3
Wenn Sie an einem BitTorrent-Schwarm teilnehmen, laden Sie Teile zu und von mehreren Peers hoch und runter gleichzeitig . Denken Sie eine Sekunde darüber nach. Zur gleichen Zeit, in der Sie einen Beitrag von einem anderen Teilnehmer anfordern, könnte ein anderer Teilnehmer das Gleiche von Ihnen verlangen. Das ist etwas ganz anderes als die Semantik von HTTP, wie Sie schon sagten. Um also direkt auf Ihre Frage einzugehen, werden andere Peers Sie nach Daten fragen, die sie interessieren :)
Bevor Sie ein Stück von einem Peer anfordern, sollten Sie sich vergewissern, dass dieser Peer das gewünschte Stück hat (sehen Sie sich die Bitfeld und haben Nachrichten ) und Sie haben die richtige würgend/interessiert Verhalten. In Anbetracht dessen sollten Sie normalerweise Daten von Ihrer Liste bekannter Peers (die Ihnen vom Tracker oder DHT mitgeteilt wurden) in Seltenste zuerst bestellen. In der Spezifikation ist davon die Rede, und es gibt hier eine Menge Optimierungen und Höflichkeitsüberlegungen. (Tit-for-tat-Verhalten, zum Beispiel.) Sie werden feststellen, dass die spec Vieles davon ist nicht klar formuliert. Das liegt daran, dass ein großer Teil der geheimen Sauce von BitTorrent-Clients in diesem Teil der Implementierung liegt :)
Ich hoffe, das hilft Ihnen ein wenig!