Я знаю, что подобные вопросы были заданы раньше, но я не смог найти конкретный ответ, который, кажется, работает. Я в основном пытаюсь написать функцию, которая будет принимать IPv6-адрес и добавить или вычесть произвольное количество IP-адресов.
Я думаю, что у меня проблема с байтовым заказом, поскольку она работает для некоторых IPv6-адресов, но не для других. Тем не менее, мне нужна помощь в попытке решить проблему, поскольку я застрял.
Я представил SSCCE, ниже которого демонстрируется проблема - она в основном преобразуется из InetAddress в BigInteger и обратно - идея состоит в том, чтобы выполнить сложение или вычитание из BigInteger посередине:
import java.math.*;
import java.net.*;
public class SSCCE {
public static void main(String[] args) {
String sIPv6 = "::00D3:0:2F3B:02AA:00FF:0";
try {
BigInteger n = new BigInteger(InetAddress.getByName(sIPv6).getAddress());
byte[] bytes = n.toByteArray();
System.out.println("Original = " + sIPv6);
System.out.println("New = " + InetAddress.getByAddress(bytes).getHostAddress());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Когда я запускаю это, я получаю следующий вывод:
Original = ::00D3:0:2F3B:02AA:00FF:0
java.net.UnknownHostException: addr is of illegal length
at java.net.InetAddress.getByAddress(Unknown Source)
at java.net.InetAddress.getByAddress(Unknown Source)
at SSCCE.main(SSCCE.java:12)
Однако, если я изменил адрес IPv6 на "2001 :: 00D3: 0: 2F3B: 02AA: 00FF: 0", тогда он отлично работает.
Проблема здесь
BigInteger n = new BigInteger(InetAddress.getByName(sIPv6).getAddress());
byte[] bytes = n.toByteArray();
Когда вы вызываете toByteArray()
возвращаемый массив достаточно велик, чтобы содержать все значимые биты адреса. Поскольку ваш адрес начинается с 0:0:...
возвращаемый массив байтов будет слишком коротким (14). Вы должны оставить его с двоичными нулями, чтобы сделать его длиной 128 бит (16 байт).
Arrays.copyOf(n, 16)
но это дополняет его в конце. Я предполагаю, что мне нужно создать байтовый массив длиной 16 и скопировать в него? Есть указатели?
Вышеприведенный ответ правильный, но не полный. В дополнение к описанному левому дополнению вы также должны иногда удалять наивысший байт, когда у вас есть 17 байтов, которые могут встречаться для адресов с 8xxx в fxxx в самом высоком байте, как описано в этом ответе: IPv6 ip (fc00: :) addr имеет незаконную длину
Другими словами, вы должны либо расширять, либо сокращать до 16 байт.