Как декодировать информацию узла Compact в Java?

Я декодировал узлы ответа find_node от router.bittorrent.com в строку и отправлял запрос 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() работает хорошо.

1 ответ

((String)nodes).getBytes();

Это предполагает определенную кодировку, которая может не подходить для этого случая. Это зависит от того, что делает используемая вами реализация bdecoder. В идеале вы должны использовать метод, который возвращает byte[] или же ByteBuffer непосредственно из закодированных данных, не проходя через String

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

Вы должны использовать | вместо +, Additionaly short это тип со знаком в Java, но порты находятся в диапазоне без знака 0-65535, поэтому вы должны расширить до int вместо. И сетевой формат является бигендовским, поэтому наиболее значимые биты порта находятся в 0-м байте, а нижняя половина - в 1-м, так что вы также получили это назад.

С помощью ByteBuffer вместо byte[] как я делаю в своей собственной реализации, это может сделать это намного менее подверженным ошибкам, поскольку позволяет напрямую получить короткое замыкание и затем преобразовать его в беззнаковое целое.

Другие вопросы по тегам