更新 #4:添加了演示 Java 代码片段,用于处理 UDP 并发送通告消息(记得首先进行连接!)请查看下面的自己的响应。
细节: 以下是一些有效种子文件的announce url(第一个是主要的)。
如果协议是HTTP,一切都很顺利,这就是我的工作方式:
如果协议是UDP,URL构造函数会抛出“java.net.MalformedURLException: unknown protocol: udp”错误。因此,我猜问题可以归结为以下内容:如何从UDP协议的URL下载资源?(希望简单明了,看不到数据报stuff)。更新#1:我在网上进行了更多调查,并得出了下面粘贴的结构(应该有效...但实际上没有,我的意思是本地可以,但与真正的跟踪器不兼容)。规格链接:http://www.bittorrent.org/beps/bep_0015.html。例如:这是我创建套接字的方式,但在有效的跟踪器上,我从未收到任何响应,因此某些内容不起作用。
问题仍然存在...我从追踪器那里没有收到任何回应(尝试了其他网址) 新问题:当完整的url包含更多信息(例如/announce)时,在elbitz.net,端口80上创建套接字是否可以?
更新#2 上面的代码似乎工作正常...我在谷歌上找到了一个实现此规范的追踪器列表,哇哦,回应发生了(例如:“udp://tracker.openbittorrent.com:80”)
新问题,规范在这里:http://www.bittorrent.org/beps/bep_0015.html - 我似乎看不到如何获取对等方列表? 在向种子追踪器的正常请求中(通过http),有两种情况:正常响应(bencoded映射)和压缩响应(以二进制形式)。 那么现在对等方列表在哪里?
从规范中可以看出,这是发布响应:
请帮忙!我还没有实现的响应消息类型是扫描和错误...但是没有一个包含我感兴趣的信息(对等方信息:IP和端口) 例如:扫描
====================================================
更新#3:我成功使其工作,下面介绍的doConnect()方法是正确的,在我的回复中有更多信息。====================================================
我主要关心的是当announce url的协议为UDP时,如何下载跟踪器响应。细节: 以下是一些有效种子文件的announce url(第一个是主要的)。
http://tracker.torrentbox.com:2710/announce
udp://elbitz.net:80/announce.php?passkey=362fc69de3402e8ef5794c7ecf7c58d4
udp://tracker.podtropolis.com:2711/announce
如果协议是HTTP,一切都很顺利,这就是我的工作方式:
String fullUrl = announceURL + "?info_hash=" + this.m_TorrentInfoHashAsURL + .. // i add the params
URL url = new URL(fullUrl);
URLConnection connection = url.openConnection();
InputStream is = connection.getInputStream();
.. //reading the stream
如果协议是UDP,URL构造函数会抛出“java.net.MalformedURLException: unknown protocol: udp”错误。因此,我猜问题可以归结为以下内容:如何从UDP协议的URL下载资源?(希望简单明了,看不到数据报stuff)。更新#1:我在网上进行了更多调查,并得出了下面粘贴的结构(应该有效...但实际上没有,我的意思是本地可以,但与真正的跟踪器不兼容)。规格链接:http://www.bittorrent.org/beps/bep_0015.html。例如:这是我创建套接字的方式,但在有效的跟踪器上,我从未收到任何响应,因此某些内容不起作用。
if full url: udp://elbitz.net:80/announce.php?passkey=362fc69de3402e8ef5794c7ecf7c58d4
this.m_TrackerHost: elbitz.net
this.m_TrackerPort: 80
private DatagramSocket m_WorkingSocket;
private DatagramSocket getWorkingSocket() {
Logger.d(TAG, "getWorkingSocket()");
if(this.m_WorkingSocket==null){
Random rnd = new Random();
for (int i = 0; i < 100; i++) {
try {
int port = 15000 + rnd.nextInt(15000); // [15000-30000)
DatagramSocket result = new DatagramSocket(port);
InetAddress trackerAddress = InetAddress.getByName(this.m_TrackerHost);
result.connect(trackerAddress, this.m_TrackerPort);
this.m_WorkingSocket = result;
} catch (SocketException se) {
Logger.w(TAG, "getWorkingSocket() - port is taken");
} catch (SecurityException se) {
Logger.w(TAG, "getWorkingSocket() - port is blocked?");
} catch (UnknownHostException e) {
Logger.w(TAG, "getWorkingSocket() - unkwnown host?");
}
}
}
return this.m_WorkingSocket;
}
& 现在是doConnect的全部代码,这应该是第一个通信阶段(下一步是announce .. 那里有类似的代码)
private boolean doConnect() throws IOException{
Logger.d(TAG, "doConnect()");
DatagramSocket workingSocket = this.getWorkingSocket();
DatagramPacket sendPacket = null, receivePacket = null;
byte[] sendData = null;
byte[] receiveData = null;
int round = 0;
Logger.d(TAG, "doConnect(): first round, timeout: " + this.getTimeoutInMillis(ACTION_ID_CONNECT, round));
while(true) {
if(round==8){
Logger.w(TAG, "doConnect() - failed to connect with tracker, consumed in vain all 8 rounds..");
return false;
}
workingSocket.setSoTimeout(this.getTimeoutInMillis(ACTION_ID_CONNECT, round));
if(receivePacket==null){
/*
Offset Size Name Value
0 32-bit integer action 0 // connect
4 32-bit integer transaction_id
8 64-bit integer connection_id
16 */
receiveData = new byte[16]; //CONNECT: at least 16 bytes
receivePacket = new DatagramPacket(receiveData, receiveData.length);
sendData = this.getConnectRequest();//return byte[] with everything..just like in specs
sendPacket = new DatagramPacket(sendData, sendData.length);
}
try {
Logger.d(TAG, "doConnect() - sending connect data: " + (Arrays.toString(sendData)));
workingSocket.send(sendPacket);
workingSocket.receive(receivePacket);
break;
} catch (SocketTimeoutException ste) {
round ++;
Logger.w(TAG, "doConnect() connect - new round: " + (round+1) + "|timeout: " + this.getTimeoutInMillis(ACTION_ID_CONNECT, round));
continue;
}
}
byte[] connectResponse = receivePacket.getData();
int actionIdFromResponse = Utils.byteArrayToInt(Utils.subArray(connectResponse, 0, 4));
int transactionIdFromResponse = Utils.byteArrayToInt(Utils.subArray(connectResponse, 4, 4));
long connectionIdFromResponse = Utils.byteArrayToLong(Utils.subArray(connectResponse, 8, 8));
if(transactionIdFromResponse!=this.m_TransactionId){
Logger.w(TAG, "doConnect() - received different transactionId");
return false;
}
if(actionIdFromResponse!=ACTION_ID_CONNECT){
Logger.w(TAG, "doConnect() - didnt received ACTION_ID_CONNECT");
return false;
}
//store connectionId
this.m_ConnectionId = connectionIdFromResponse;
return true;
}
问题仍然存在...我从追踪器那里没有收到任何回应(尝试了其他网址) 新问题:当完整的url包含更多信息(例如/announce)时,在elbitz.net,端口80上创建套接字是否可以?
更新#2 上面的代码似乎工作正常...我在谷歌上找到了一个实现此规范的追踪器列表,哇哦,回应发生了(例如:“udp://tracker.openbittorrent.com:80”)
新问题,规范在这里:http://www.bittorrent.org/beps/bep_0015.html - 我似乎看不到如何获取对等方列表? 在向种子追踪器的正常请求中(通过http),有两种情况:正常响应(bencoded映射)和压缩响应(以二进制形式)。 那么现在对等方列表在哪里?
从规范中可以看出,这是发布响应:
/*
Offset Size Name Value
0 32-bit integer action 1 // announce
4 32-bit integer transaction_id
8 32-bit integer interval
12 32-bit integer leechers
16 32-bit integer seeders
20 + 6 * n 32-bit integer IP address
24 + 6 * n 16-bit integer TCP port
20 + 6 * N */
从我的测试中,我总是收到相同的字段值:IP地址和TCP端口... 再加上每个请求只有一个响应..所以这肯定不是它!我需要一个对等方列表!请帮忙!我还没有实现的响应消息类型是扫描和错误...但是没有一个包含我感兴趣的信息(对等方信息:IP和端口) 例如:扫描
Offset Size Name Value
0 32-bit integer action 2 // scrape
4 32-bit integer transaction_id
8 + 12 * n 32-bit integer seeders
12 + 12 * n 32-bit integer completed
16 + 12 * n 32-bit integer leechers
8 + 12 * N