smile908

导航

使用int来存储ip地址

上次在面试的时候面试官问了我一个比较有意思的问题,如何用一个int来存储一个IP地址。面试官竟然问了,那么就有他的一个可行性,于是,我就开始整理我的思绪。

现在的ipv4是点分十进制的,比如,1129.168.255.25,转化为二进制为10000001101010001111111100011001。一共32位,刚好一个int也是32位,我们可以将ip地址进行一个处理,转化为二进制,然后一位位的存储在int的每一位中,不就可以了吗。于是,我开始了我的编码。

public class ipByint {

//主函数
public static void main(String[] args) {
String ip = "129.168.255.25";
String binaryString=bytetoint(getByte(ip));
System.out.println("ip转化为二进制:"+binaryString);
System.out.println("这里是int的最大值:"+Integer.MAX_VALUE);
}

 

//将ip处理存储在Byte数组中
public static Byte[] getByte(String ip) {
Byte[] arrs = new Byte[4];
String[] ipaddStrings = ip.split("\\.");
arrs[0] = (byte) Integer.parseInt(ipaddStrings[0]);
arrs[1] = (byte) Integer.parseInt(ipaddStrings[1]);
arrs[2] = (byte) Integer.parseInt(ipaddStrings[2]);
arrs[3] = (byte) Integer.parseInt(ipaddStrings[3]);
//System.out.println(arrs[0]);
return arrs;
}

//将Byte数组的十进制数字转化为二进制,拼接成一个32位二进制字符串
public static String bytetoint(Byte[] arrs) {
StringBuffer stringBuffer=new StringBuffer();
for (int i = 0; i < arrs.length; i++) {
String s=Integer.toBinaryString(arrs[i]&0xFF);
int length=s.length();
if (length<8) {
for (int j = 0; j < 8-length; j++) {
s="0"+s;
}
}
stringBuffer.append(s);
}
return stringBuffer.toString();
}

//二进制转化为十进制
public static int binary2ten(String s) {
return Integer.parseInt(s,2);
}
}

这是我大概的代码,运行结果如下。

 

 

 

 

这里我们对ip地址字符串进行了一个处理,将十进制的ip地址转化为了32位的二进制,可是当我将这一串二进制数字存入int的时候,却报错了。

经过检查发现这个二进制转化为为十进制的数字为2175336217,而int的十进制范围为-2147483648~+2147483647。很明显ip转化的这个数字明显比

int的上限高一点,所以出现了范围的错误。

对于以上情况,我暂时有两种方案

第一种,使用无符号的int,无负号的int的范围为0~4294967295。我们发现这个数字高达42亿,能够满足所有的IP地址的存储了

(java不支持无符号啦,当然这只是一个思路,我们可以用其他的一个语言进行编码)

 

第二种稍微复杂一点,我们先来看看jvm是怎么来处理这个问题的,我们知道byte的范围是-128-127,可byte怎么来存储一个大于127小于255的数字呢。

我们来看看运行结果。

 

 

 我们的IP地址为129.168.255.25,我们发现有三位数字都大于127,他们被jvm处理变成了一个负数来进行表示,我们来看看他是怎么做到的。

129 的原码为 1000 0001

129的反码为  1111  1110 原码变反码,首位符号为0为正,1为负数。其他位取反

129的补码为  1111  1111 补码就是原码加1

由于第一位是符号为,故补码的十进制为-127

 

168的源码为 1010 1000

168的反码为 1101 0111

168的补码为 1101 1000

补码的十进制为-88

 

255的原码为1111 1111

255的反码为1000 0000

255的补码为1000 0001

补码的十进制为-1

因此,我们的int范围超了。我们可以转化为补码进行一个存储,当需要逆向的时候的,我们就可以补码转原码,原码转成十进制之后进行一个处理,这样我们就可以从

一个32位补码到原码到转化为十进制,变成一个字符串的ip了。

 

下面讲解如何补码到原码,比如刚刚的255的补码为1000 0001

255的补码为1000 0001

反码一次,第一位符号为不变1111 0001

加1 1111 1111

原码就为1111 1111,十进制的数字为255.

这样我们就完成了一个补码到原码的逆向操作了

 

posted on 2022-08-11 14:15  smile908  阅读(1016)  评论(0编辑  收藏  举报