【问题标题】:Going from 127.0.0.1 to 2130706433, and back again从 127.0.0.1 到 2130706433,然后再返回
【发布时间】:2011-01-15 12:31:16
【问题描述】:

使用标准 Java 库,从 IPV4 地址的点分字符串表示 ("127.0.0.1") 到等效整数表示 (2130706433) 的最快方法是什么。

相应地,反转上述操作的最快方法是什么 - 从整数2130706433 到字符串表示"127.0.0.1"

【问题讨论】:

    标签: java ip-address


    【解决方案1】:

    您也可以使用Google Guava InetAddress

    String ip = "192.168.0.1";
    InetAddress addr = InetAddresses.forString(ip);
    // Convert to int
    int address = InetAddresses.coerceToInteger(addr);
    // Back to str 
    String addressStr = InetAddresses.fromInteger(address));
    

    【讨论】:

    • 我认为这是最简单的。除非您关心微秒级性能,否则请使用处理所有字节序和符号的标准库
    【解决方案2】:

    使用the IPAddress Java library 很简单,每个方向一行代码。 免责声明:我是该库的项目经理。

        IPv4Address loopback = new IPAddressString("127.0.0.1").getAddress().toIPv4();
        System.out.println(loopback.intValue());
        IPv4Address backAgain = new IPv4Address(loopback.intValue());
        System.out.println(backAgain);
    

    输出:

        2130706433
        127.0.0.1
    

    【讨论】:

      【解决方案3】:

      另一种方式:

      public static long ipToLong(String ipAddress) {
      
          String[] ipAddressInArray = ipAddress.split("\\.");
      
          long result = 0;
          for (int i = 0; i < ipAddressInArray.length; i++) {
      
              int power = 3 - i;
              int ip = Integer.parseInt(ipAddressInArray[i]);
              result += ip * Math.pow(256, power);
      
          }
      
          return result;
        }
      

      【讨论】:

        【解决方案4】:

        字符串转整数:

        int pack(byte[] bytes) {
          int val = 0;
          for (int i = 0; i < bytes.length; i++) {
            val <<= 8;
            val |= bytes[i] & 0xff;
          }
          return val;
        }
        
        pack(InetAddress.getByName(dottedString).getAddress());
        

        整数转字符串:

        byte[] unpack(int bytes) {
          return new byte[] {
            (byte)((bytes >>> 24) & 0xff),
            (byte)((bytes >>> 16) & 0xff),
            (byte)((bytes >>>  8) & 0xff),
            (byte)((bytes       ) & 0xff)
          };
        }
        
        
        InetAddress.getByAddress(unpack(packedBytes)).getHostAddress()
        

        【讨论】:

        • 127.0.0.1 给出 2130706433,但 255.255.255.255 没有给出 4294967295。签名与未签名的问题?
        • 以无符号形式打印,将结果转换为 long 并屏蔽高位:((long)packedBytes)&amp;0xffffffff
        • 字节在Java中最多为2^7-1,这样每个字节将无法显示任何大于127的整数。正确的做法是使用int来存储数字。跨度>
        【解决方案5】:

        如果您需要学习长手数学,您可以使用 Substr 删除八位字节。 将表示类的第一个八位字节乘以 (256*256*256) 或 (2^24) 秒乘以 (256*256) (2^16) 第三乘以 (256) (2^8) 第四乘以 1 或 (2^0)

        127 * (2^24) + 0 *(2^16) + 0 * (2^8) + 1 * (2^0) 2130706432 + 0 + 0 + 1 = 2130706433

        【讨论】:

          【解决方案6】:

          我修改了我原来的答案。在 Sun 的 InetAddress 实现中,hashCode 方法生成 IPv4 地址的整数表示,但正如评论者正确指出的那样,JavaDoc 不能保证这一点。因此,我决定改用ByteBuffer类来计算IPv4地址的值。

          import java.net.InetAddress;
          import java.nio.ByteBuffer;
          
          // ...
          
          try {
              // Convert from integer to an IPv4 address
              InetAddress foo = InetAddress.getByName("2130706433");
              String address = foo.getHostAddress();
              System.out.println(address);
          
              // Convert from an IPv4 address to an integer
              InetAddress bar = InetAddress.getByName("127.0.0.1");
              int value = ByteBuffer.wrap(bar.getAddress()).getInt();
              System.out.println(value);
          
          } catch (Exception e) {
              e.printStackTrace();
          }
          

          输出将是:

          127.0.0.1
          2130706433
          

          【讨论】:

          • hashCode() 是否明确定义为进行 4 字节到 int 的转换?如果不是,我怀疑是这样。请注意,解释总是好的。
          • IP地址到int的映射需要双射。 hashCode 不保证这一点。
          • 这应该被否决。 Javadocs 中没有任何内容可以保证这种行为,它恰好是目前(明智的)Sun 实现。 Sun 可以将其更改为仅返回一个常量,它仍然可以正常运行,但您的示例会失败。
          • 您是正确的,InetAddress 的 hashCode() 方法没有指定如何计算散列。我将把答案留在这里,因为它使用 InetAddress 的标准实现“工作”。
          • 我已根据您的担忧更新了我的答案。我的示例现在使用 ByteBuffer 类来计算 IPv4 地址的整数值,而不是依赖 InetAddress 的 hashCode 方法。
          【解决方案7】:

          我没试过。性能,但最简单的方法可能是使用 NIO ByteBuffer

          例如

           byteBuffer.put(integer).array();
          

          会返回一个表示整数的字节数组。您可能需要修改字节顺序。

          【讨论】:

          • 为什么不直接选择一个字节顺序并使其成为 ByteBuffer 的字节顺序?这样您就不必担心不同机器上的不同默认字节顺序。编辑:没关系,默认是大端。
          猜你喜欢
          • 2023-01-25
          • 2014-01-11
          • 2011-10-11
          • 2015-10-05
          • 1970-01-01
          • 2018-09-30
          • 2011-04-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多