我将来自router.bittorrent.com的find_node响应的节点解码为字符串,并向解码的“节点”发送了一个find_node请求,但是我从未修改过来自“节点”的find_node响应,我怀疑解码方式“节点” “这是错的,这是代码:
byte[] nodesBytes = ((String)nodes).getBytes();
ByteBuffer buffer = ByteBuffer.wrap(nodesBytes);
int size = nodesBytes.length / 26;
for (int i = 0; i < size; i++) {
byte[] bytes = new byte[26];
byte[] nodeIdBytes = Arrays.copyOfRange(bytes, 0, 20);
byte[] ipBytes = Arrays.copyOfRange(bytes, 20, 24);
byte[] portBytes = Arrays.copyOfRange(bytes, 24, 26);
RoutingTable.RoutingNode routingNode = new RoutingTable.RoutingNode();
try {
routingNode.nodeId = nodeIdBytes;
routingNode.ip = InetAddress.getByAddress(ipBytes);
routingNode.port = (((((short)portBytes[1]) << 8) & 0xFF00) + (((short)portBytes[0]) & 0x00FF));
} catch (UnknownHostException e) {
e.printStackTrace();
}
send(routingNode);
}
解码字符串代码是
private static String decodeString(ByteBuffer byteBuffer) {
try {
StringBuilder buffer = new StringBuilder();
int type = byteBuffer.get();
buffer.append((char) type);
do {
byte a = byteBuffer.get();
if (a == SEPARATOR) {
break;
} else {
buffer.append((char) a);
}
} while (true);
int length = Integer.parseInt(buffer.toString());
byte[] bytes = new byte[length];
byteBuffer.get(bytes);
String value = new String(bytes, "UTF-8");
logger.debug(value);
return value;
} catch (Exception e) {
logger.error("", e);
}
return "";
}
有问题吗?
PS: send()函数运行良好。
答案 0 :(得分:0)
((String)nodes).getBytes();
假定特定的编码,这可能不适用于这种情况。这取决于你正在使用的bdecoder实现。理想情况下,您应该使用直接从bencoded数据返回byte[]
或ByteBuffer
的方法,而不通过String
routingNode.port = (((((short)portBytes[1]) << 8) & 0xFF00) + (((short)portBytes[0]) & 0x00FF));
您应该使用|
代替+
。 Additionaly short
是java中的签名类型,但端口的无符号范围为0-65535,因此您应该扩展为int
。
并且网络格式是bigendian,因此端口的最高有效位在第0个字节中,而在第1个字节中是下半部分,因此您也可以向后移动。
使用ByteBuffer
代替byte[]
,因为我in my own implementation可以减少错误,因为它允许你直接得到一个简短的然后将它转换为unsigned int。