用 Java 实现的 Bittorrent Peer Wire 协议
Posted
技术标签:
【中文标题】用 Java 实现的 Bittorrent Peer Wire 协议【英文标题】:Bittorrent Peer Wire Protocol implementing in Java 【发布时间】:2009-06-21 12:46:14 【问题描述】:我有几个关于 Bittorrent Peer Wire 协议的问题。 我正在尝试使用 this spec 在 Java 中实现它。
在对等线协议部分它说所有整数都是四字节大端值。 AFAIK java使用大端。这是否意味着如果我想发送一个窒息消息
扼流圈:
我只是写到 sokcet 1 后跟 0 吗?
至于我的第二个问题。当请求一块时,我认为多个文件是一个大的连续文件吗?还是考虑单个文件?因为片段长度不会与文件对齐,所以一个索引可以同时包含一个文件的结尾和另一个文件的开头?
至于我的最后一个问题,当我打开与对等方的连接并发送我的握手时,我是继续请求片段还是请求然后等待一段时间看看它是否会向我们请求某些东西?谈话是如何进行的?我主要完成了 http 类型的网络编程,我要求一些东西等待响应。但是,如果我一直在请求作品,我将如何发送作品?
【问题讨论】:
【参考方案1】:问题 1
坚持简单的方法,如果您使用基于流的 I/O,则在编写原始类型(例如 byte、int 时使用 DataInputStream 和 DataOutputStream >、长等):
Socket s; // assume this is already connected
DataOutputStream out = new DataOutputStream( s.getOutputStream );
out.writeByte( 1 );
out.writeInt( 0 );
out.flush(); // optional
如果您使用的是非阻塞 I/O(例如 java.nio 包中的类),请使用 ByteBuffers:
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
(请注意,通常您是在电线上传输 blocks,它们是碎片的片段。我将在此略过:)
发送/接收片段时,最好将文件(或文件)视为连续的,就像您说的那样。 .torrent 文件在信息字典中包含有关文件边界的信息。在multi-file case中,每个文件都有路径和长度; single file case 有一个可选的名称和长度。由于您知道片段大小、片段数量和总内容长度(全部来自 .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 swarm 时,您将同时向多个对等方上传和下载片段。想一想。在您向某个同伴请求一块的同时,另一个同伴可能正在向您做同样的事情。正如您已经指出的,与 HTTP 的语义完全不同。因此,要直接回答您的问题,其他同行会要求您提供他们感兴趣的数据。 :)
只是为了确保,在您向同伴请求一块 a 之前,请确保该同伴拥有您想要的一块(查看 bitfield and have messages)并且您已经尊重了正确的 choking/interested 行为。鉴于此,您通常想要做的是以最稀有的优先顺序从已知对等点列表(跟踪器或 DHT 告诉您的)请求数据。规范谈到了这一点,这里有很多优化和礼貌考虑。 (例如,以牙还牙的行为。)您可能会注意到spec 并没有说明很多。这是因为 BitTorrent 客户端的许多秘诀都在于这部分实现。 :)
希望对你有所帮助!
【讨论】:
请注意,根据规范,id 字段是单个字节,而不是 int。以上是关于用 Java 实现的 Bittorrent Peer Wire 协议的主要内容,如果未能解决你的问题,请参考以下文章
一个功能齐全的 BitTorrent 库,支持 DHT磁力链接加密等功能