【问题标题】:How to decode Compact node info in java?如何在java中解码紧凑节点信息?
【发布时间】:2017-08-15 10:11:30
【问题描述】:

我将来自 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() 函数运行良好。

【问题讨论】:

    标签: java p2p bittorrent dht kademlia


    【解决方案1】:

    ((String)nodes).getBytes();

    这假定了一个特定的编码,这可能不适合这种情况。这取决于您使用的 bdecoder 实现是做什么的。理想情况下,您应该使用直接从编码数据返回byte[]ByteBuffer 的方法,而无需通过String

    routingNode.port = (((((short)portBytes[1]) &lt;&lt; 8) &amp; 0xFF00) + (((short)portBytes[0]) &amp; 0x00FF));

    您应该使用| 而不是+。另外short 是java 中的有符号类型,但端口在0-65535 的无符号范围内,因此您应该改为扩展为int。 并且网络格式是 bigendian,所以端口的最高有效位在第 0 个字节,下半部分在第一个字节,所以你也把它倒过来了。

    使用ByteBuffer 而不是byte[] 就像我使用in my own implementation 可以大大减少出错的可能性,因为它允许您直接获取一个short 然后将其转换为一个无符号整数。

    【讨论】:

    • 我看不出这有什么关系。它甚至没有在您的代码中调用,也没有解决我所说的任何问题。您的代码中可识别的问题是 bdecoding(String 与 ByteBuffer)、字节序转换和位操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多