【问题标题】:Conversion IPv6 to long and long to IPv6将 IPv6 转换为 long 并将 long 转换为 IPv6
【发布时间】:2013-07-26 09:23:41
【问题描述】:

我应该如何执行从 IPv6 到 long 的转换,反之亦然?

到目前为止我有:

    public static long IPToLong(String addr) {
            String[] addrArray = addr.split("\\.");
            long num = 0;
            for (int i = 0; i < addrArray.length; i++) {
                    int power = 3 - i;

                    num += ((Integer.parseInt(addrArray[i], 16) % 256 * Math.pow(256, power)));
            }
            return num;
    }

    public static String longToIP(long ip) {
            return ((ip >> 24) & 0xFF) + "."
                    + ((ip >> 16) & 0xFF) + "."
                    + ((ip >> 8) & 0xFF) + "."
                    + (ip & 0xFF);

    }

这是正确的解决方案还是我错过了什么?

(如果解决方案对 ipv4 和 ipv6 都有效,那就完美了)

【问题讨论】:

    标签: java ip type-conversion ipv6 long-integer


    【解决方案1】:

    您也可以使用 java.net.InetAddress
    它适用于 ipv4 和 ipv6(所有格式)

    public static BigInteger ipToBigInteger(String addr) {
        InetAddress a = InetAddress.getByName(addr)
        byte[] bytes = a.getAddress()
        return new BigInteger(1, bytes)
    }
    

    【讨论】:

    • 这将为您提供 IP 范围上半部分的负数。如果您希望它是无符号的,则需要传入符号以使其保持正值(即 new BigInteger(1, bytes))。
    【解决方案2】:

    IPv6 地址是一个 128 位数字,如 here 所述。 Java 中的 long 以 64 位表示,因此您需要另一种结构,例如 BigDecimal 或两个 long(一个包含两个 long 数组的容器,或者只是一个包含两个 long 数组的容器)来存储 IPv6 地址。

    下面是一个例子(只是给你一个想法):

    public class Asd {
    
        public static long[] IPToLong(String addr) {
            String[] addrArray = addr.split(":");//a IPv6 adress is of form 2607:f0d0:1002:0051:0000:0000:0000:0004
            long[] num = new long[addrArray.length];
            
            for (int i=0; i<addrArray.length; i++) {
                num[i] = Long.parseLong(addrArray[i], 16);
            }
            long long1 = num[0];
            for (int i=1;i<4;i++) {
                long1 = (long1<<16) + num[i];
            }
            long long2 = num[4];
            for (int i=5;i<8;i++) {
                long2 = (long2<<16) + num[i];
            }
            
            long[] longs = {long2, long1};
            return longs;
        }
        
        
        public static String longToIP(long[] ip) {
            String ipString = "";
            for (long crtLong : ip) {//for every long: it should be two of them
    
                for (int i=0; i<4; i++) {//we display in total 4 parts for every long
                    ipString = Long.toHexString(crtLong & 0xFFFF) + ":" + ipString;
                    crtLong = crtLong >> 16;
                }
            }
            return ipString;
        
        }
        
        static public void main(String[] args) {
            String ipString = "2607:f0d0:1002:0051:0000:0000:0000:0004";
            long[] asd = IPToLong(ipString);
            
            System.out.println(longToIP(asd));
        }
    }
    

    【讨论】:

    • 好的,我会这样做的。转换呢?做对了吗?
    • 很容易测试:执行 longToIP(IPToLong("122.122.122.124")) 你会得到 "34.34.34.36" 而不是原来的 "122.122.122.124" 这意味着不正确。
    • 问题如下:您尝试将 IPv4 的代码调整为 IPv6,这是不正确的,因为在 IPv4 中,数字以基数 10 编码(IP 地址中的数字 124“122.122. 122.124" 以 10 为基数),但在 IPv6 中,所有部分都以十六进制编码。这意味着,您必须以某种方式确定 IP 地址的版本,然后做出一些决定,以便为两个版本使用一种方法。
    • 感谢您的解释。但是我仍然不知道如何为 IPv6 执行转换。您能否提供指向某些来源或示例/教程的链接?我找不到任何有用的东西。
    • 添加了一段工作代码,但请注意缺少一些检查(如无效字符串),所以这对于您的家庭作业来说是可以的,但对于生产来说还没有经过足够的测试。
    【解决方案3】:

    IPv6 地址不能长存储。您可以使用 BigInteger 而不是 long。

    public static BigInteger ipv6ToNumber(String addr) {
        int startIndex=addr.indexOf("::");
    
        if(startIndex!=-1){
    
    
            String firstStr=addr.substring(0,startIndex);
            String secondStr=addr.substring(startIndex+2, addr.length());
    
    
            BigInteger first=ipv6ToNumber(firstStr);
    
            int x=countChar(addr, ':');
    
            first=first.shiftLeft(16*(7-x)).add(ipv6ToNumber(secondStr));
    
            return first;
        }
    
    
        String[] strArr = addr.split(":");
    
        BigInteger retValue = BigInteger.valueOf(0);
        for (int i=0;i<strArr.length;i++) {
            BigInteger bi=new BigInteger(strArr[i], 16);
            retValue = retValue.shiftLeft(16).add(bi);
        }
        return retValue;
    }
    
    
    public static String numberToIPv6(BigInteger ipNumber) {
        String ipString ="";
        BigInteger a=new BigInteger("FFFF", 16);
    
            for (int i=0; i<8; i++) {
                ipString=ipNumber.and(a).toString(16)+":"+ipString;
    
                ipNumber = ipNumber.shiftRight(16);
            }
    
        return ipString.substring(0, ipString.length()-1);
    
    }
    
    public static int countChar(String str, char reg){
        char[] ch=str.toCharArray();
        int count=0;
        for(int i=0; i<ch.length; ++i){
            if(ch[i]==reg){
                if(ch[i+1]==reg){
                    ++i;
                    continue;
                }
                ++count;
            }
        }
        return count;
    }
    

    【讨论】:

      【解决方案4】:

      维诺德的回答是对的。但仍有一些地方可以改进。

      首先,在方法'countChar'中,'continue'应该替换为'break'。

      其次,必须考虑一些边界条件。

      public static BigInteger ipv6ToNumber(String addr) {
          int startIndex = addr.indexOf("::");
          if (startIndex != -1) {
              String firstStr = addr.substring(0, startIndex);
              String secondStr = addr.substring(startIndex + 2, addr.length());
              BigInteger first = new BigInteger("0");
              BigInteger second = new BigInteger("0");
              if (!firstStr.equals("")) {
                  int x = countChar(addr, ':');
                  first = ipv6ToNumber(firstStr).shiftLeft(16 * (7 - x));
              }
              if (!secondStr.equals("")) {
                  second = ipv6ToNumber(secondStr);
              }
              first = first.add(second);
              return first;
          }
      
          String[] strArr = addr.split(":");
          BigInteger retValue = BigInteger.valueOf(0);
          for (int i = 0; i < strArr.length; i++) {
              BigInteger bi = new BigInteger(strArr[i], 16);
              retValue = retValue.shiftLeft(16).add(bi);
          }
          return retValue;
      }
      
      public static int countChar(String str, char reg){
          char[] ch=str.toCharArray();
          int count=0;
          for(int i=0; i<ch.length; ++i){
              if(ch[i]==reg){
                  if(ch[i+1]==reg){
                      ++i;
                      break;
                  }
                  ++count;
              }
          }
          return count;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-25
        • 2010-12-31
        • 2021-10-24
        相关资源
        最近更新 更多