I'm writing a dht server and meet some problem. I send the find_node request to bootstraps, and they return me some compact node info(416bytes) which contains 16 nodes info then i bdecode and store the ip address and port, continue send find_node request to these nodes,but i get no response.
Server code here(receive packet and start a new thread to add nodes to a list)
public void run() {
try {
while (true) {
byte[] buffer_rcv = new byte[1024];
DatagramPacket recvPacket = new DatagramPacket(buffer_rcv, buffer_rcv.length);
socket.receive(recvPacket);
System.out.println("get!!!");
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
LinkedList<Node> nodes = BDecode.bdecode_find_node(recvPacket);
for (Node n : nodes) {
table.add_node(n);
}
System.out.println("table size" + table.get_all_nodes().size());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
System.out.println("waiting new packet!!!!!!!");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I download the jbittorrent api from sourceforge and use it to bdecode
public static LinkedList<Node> bdecode_find_node(DatagramPacket recvPacket) throws IOException {
byte[]nodes_compact_info = (byte[]) ((Map) new BDecoder().decodeByteArray(recvPacket.getData()).get("r")).get("nodes");
byte[]node_info = new byte[26];
byte[]node_id = new byte[20];
byte[]ip_byte = new byte[4];
byte[]port_byte = new byte[2];
int port;
LinkedList<Node> nodes = new LinkedList<>();
//System.out.println("nodes_compact_info.length"+nodes_compact_info.length);
for (int i = 0;i<nodes_compact_info.length/26;i++) { //416 = 16 * 26byte_per_node
//0-19 id 20 21 22 23 ip 24 25 port
node_info = Utils.subArray(nodes_compact_info, i*26, 26);
node_id=Utils.subArray(node_info, 0, 20);
ip_byte = Utils.subArray(node_info, 20, 4);
String ip = "";
for (int j = 0;j<ip_byte.length;j++) {
ip+=Utils.byteToUnsignedInt(node_info[j]);
ip+=".";
}
ip = ip.substring(0, ip.length()-1);
//System.out.println(ip);
port_byte = Utils.subArray(node_info, 24, 2);
port = Utils.byteArrayToInt(port_byte);
nodes.add(new Node(node_id, ip, port, new Date()));
}
return nodes;
}
Finally i send find_node request to every node in list
public void get_neighbor() {
ArrayList<Node> nodes = table.get_all_nodes();
System.out.println("*********get_neighbor!!!");
for (Node n : nodes) {
try {
byte[] find_node_query = BEncode.find_node(this.id, this.id);
DatagramPacket sendPacket = new DatagramPacket(find_node_query, find_node_query.length,
InetAddress.getByName(n.getIp()), n.getPort());
for (int i = 0;i<5;i++)
socket.send(sendPacket);
System.out.println("packet send to " + n.getIp() + ":" + n.getPort());
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
System.out.println("UnknownHostException" + n.getIp());
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("cant send packet");
}
}
}
i have stuck there for some days, and try a lot of ways to find where go wrong, help me please.
this is returned from bootstrap and after bdecoding node compact info