`
aokunsang
  • 浏览: 816076 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

IP地址与长整数之间的转换详解

    博客分类:
  • Java
 
阅读更多

今天终于搞懂了ip地址和整数之间的转换, 在这里和大家分享一下心得,唠叨一把。
事件起因:
   项目中用到通过ip地址获取城市名称,这样的原码网上一搜一大把,基本上都是lumaQQ的东西,在这里夸赞一番,确
实不错。它的原码里面用到了ip和整数之间的转换,长途跋涉进行了研究(只因大学计算机基础没有学好,哎... 重新研
究二进制,八进制,16进制),皇天不负有心人啊,终于搞定了。
事件过程:
   先得了解ip地址的“构造”是由32位二进制数组成的,然后再研究二进制的表示和Java的按位运算(在前面的博文中有
介绍),想了解ip和整数之间的转换,这个知识是必备的。
$1 :Ip转换为长整数的代码:

  public static long ipToLong(String ipString){
        long result = 0;
        java.util.StringTokenizer token = new java.util.StringTokenizer(ipString,".");
        result += Long.parseLong(token.nextToken())<<24;
        result += Long.parseLong(token.nextToken())<<16;
        result += Long.parseLong(token.nextToken())<<8;
        result += Long.parseLong(token.nextToken());
        return result;
    }

 

原理:ip地址的每段可以看成是一个0-255的整数,把每段拆分成一个二进制形式组合起来,然后把这个二进制数转变成
一个长整数。

举例:一个ip地址为10.0.3.193
每段数字             相对应的二进制数
10                   00001010
0                    00000000
3                    00000011
193                  11000001
组合起来即为:00001010 00000000 00000011 11000001,转换为10进制数就是:167773121,即该IP地址转换后的数字就是它了。


在上面的方法中,原理都是一样的。我用到了位移操作,因为它就是操作的二进制数,使用位移操作很方面、直观。
Long.parseLong(token.nextToken())<<24 就是把第一段数字表示的二进制数左移了24位,(记住:按位操作符都操作的整数的二进制数)

得到00001010 00000000 00000000 00000000;
依次类推:
Long.parseLong(token.nextToken())<<16,得到00000000 00000000 00000000 00000000;
Long.parseLong(token.nextToken())<<8,得到00000000 00000000 00000011 00000000;
Long.parseLong(token.nextToken()),最低位不用移动,得到00000000 00000000 00000000 11000001;
把这四个二进制数转换为整数后相加和00001010 00000000 00000011 11000001表示的二进制数是一样的(这个就不多说了,明白人一看就知道了)。
$2 :长整数转换为Ip的代码:

  public static String longToIp(long ipLong){
        StringBuilder sb = new StringBuilder();
        sb.append(ipLong>>>24);sb.append(".");
        sb.append(String.valueOf((ipLong&0x00FFFFFF)>>>16));sb.append(".");
        sb.append(String.valueOf((ipLong&0x0000FFFF)>>>8));sb.append(".");
        sb.append(String.valueOf(ipLong&0x000000FF));
        return sb.toString();
    }

 
原理:很简单的,就是$1的“反编码”(就这样先叫着),先把这个长整数转换成一个32位的二进制数。从左到右,每8位
进行一下分割,就得到4段8位的二进制数,把这些二进制数转换成整数然后加上"."就是这个ip地址了。

举例:167773121
二进制表示形式为:00001010 00000000 00000011 11000001
分割成四段:00001010,00001010,00000011,11000001,分别转换为整数后加上“.”就得到了10.0.3.193。
每段怎么计算为整数的呢,比如00001010,一个整数是32位的整数,所以前面全部补0(也就是说把该段的8位看成是低位数字,高位全部补0,得到一个32位的二进制数,即为一个整数的二进制数表示形式),由此可以得到
00000000 00000000 00000000 00001010,就是传说中的10,其他三个数字也就相继可以得到了。

上面的longToIp方法使用也是与$1中位移操作正好相反。
先得到第一段(它是二进制数的左边)的整数,那个长整型的二进制数字无符号左移24位(正好是前面都补0),得到一个二
进制数即为最高位的数字。即可以用位移实现ipLong>>>24(>>>操作的是ipLong的二进制数);
想得到第二段,就要把ipLong表示的二进制数进行无符号左移16位,但是它的左边不一定为0(还有第一段数字的二进制数
呢),所以在移位之前先把前面的的8位置为0,就可以用ipLong&0x00FFFFFF表示。
0x00FFFFFF是什么呢?为什么要&0x00FFFFFF呢?

0x00FFFFFF是一个16进制数,它的二进制表示形式为00000000 11111111 11111111 11111111,结合前篇博文【传说中的Java基础东西(按位操作运算)】的&用法,你就很清楚为啥要&0x00FFFFFF了,它可以使前8为置为0,后16位是1或者0还是不变的。
然后就可以肆无忌惮的把ipLong表示的二进制数进行无符号的左移16位。
ipLong&0x00FFFFFF 可以得到00000000 00000000 00000011 11000001,然后让它>>>16位,
得到00000000 00000000 00000000 00000000,即为第二段的数字0、
依次类推、
最后一段直接把前24位都置为0,然后计算出来的整数即为最后一段的值了。

OK,写了那么多,其实就是一个简单的把ip转换为整数,中间主要是操作了二进制数,想想也很简单,为啥以前咱就不会
呢。想了一下,原来还是自己的计算机基础的二进制没有学好,后悔啊,又浪费我的生命去重新学习....

分享到:
评论
2 楼 fireinjava 2016-06-26  
longToip直接用ipToLong反过来就好了
public static String longToIp(long ipLong) {
StringBuffer ip = new StringBuffer();
String binaryString = Long.toBinaryString(ipLong);
binaryString = StringUtils.leftPad(binaryString, 32, "0");
for (int i = 1; i <= 4; i++) {
String substring = binaryString.substring((i - 1) * 8, i *;
ip.append(Integer.valueOf(substring, 2)).append(i < 4 ? "." : "");
}
return ip.toString();
}
1 楼 lenomon 2012-03-11  
博主讲的比较复杂,这篇讲的比较简洁IP地址与整数之间的转换

相关推荐

    php IP转换整形(ip2long)的详解

    例如,在MySQL数据库中,INET_ATON函数可以将IP地址转换成网络字节序的32位整数,而INET_NTOA函数则将32位整数转换回IP地址字符串。这样做的好处是数据库自身的实现通常经过优化,能够确保不同系统平台之间的兼容性...

    详解Python判定IP地址合法性的三种方法

    然后对这个列表进行遍历,确保每个元素都可以转换为一个介于0到255之间的整数,并且列表长度恰好为4。如果这些条件都满足,那么输入的字符串就是一个合法的IP地址。字符串拆解法的优势在于它的通用性高,无需任何...

    IP地址合法性判断(适合新手)

    ### IP地址合法性判断知识点详解 #### 一、IP地址基础知识 IP地址(Internet Protocol Address)是一种用于标识互联网上的计算机或网络设备的唯一地址。IPv4是最常用的版本之一,由32位二进制数表示,通常被分为四...

    子网掩码的计算与划分详解

    例如,要计算 IP 地址 192.9.200.13 的网络号和主机号,需要将子网掩码 255.255.255.0 转换为二进制,然后与 IP 地址进行 AND 运算,得到网络号 192.9.200.0。然后,将子网掩码的二进制值取反后,与 IP 地址进行 AND...

    IP 基础知识“全家桶”,敖丙45 张图一套带走你.pdf

    - **点分十进制表示法**:将32位IP地址分成4组,每组8位,然后将每组转换为十进制数字,并用点号`.`分隔。 **2.2 IP地址的数量** 理论上,IPv4地址的最大数量为\(2^{32}\)个,即约43亿个不同的地址。然而,由于IP...

    远程开机关机-从零教起.docx

    - 首先,将用户输入的点式IP地址转换为无符号长整数。 - 使用`SendARP`函数发送ARP请求,并接收目标计算机的MAC地址。 - 将收到的MAC地址转换为字符串格式,方便展示。 - 为了获取整个网络中的MAC地址,可以循环...

    DELPHI下的Winsock编程.docx

    IP地址通常以点分十进制形式表示(如 192.168.1.1),但在 `sin_addr` 字段中存储为一个无符号长整数。DELPHI 提供了一个名为 `inet_addr` 的支持函数,可以将点分十进制的 IP 地址转换成该格式。 ### 总结 在...

    Python3获取电脑IP、主机名、Mac地址的方法示例

    4. **获取IP地址**:通过`socket.gethostbyname()`函数,结合上一步获取到的主机名来获取IP地址。 5. **获取MAC地址**:利用UUID模块中的`uuid.getnode()`函数来获取MAC地址的整数值表示,再进行格式化处理得到标准...

    计算机网络.doc————电子版_doc版

    2. **地址转换**:在数据传输过程中,IP地址和MAC地址之间的转换通过ARP协议实现。 3. **ARP协议**:ARP协议用于实现IP地址到硬件地址的映射。每个主机维护一个ARP高速缓存表,记录已知的IP地址与硬件地址之间的对应...

    C语言网络通信编程C语言网络通信编程.docx

    - `htonl`: 主机到网络长整数转换 - `ntohs`: 网络到主机短整数转换 - `ntohl`: 网络到主机长整数转换 - **网络地址转换** - `inet_addr()`: 将字符串形式的 IP 地址转换为 `unsigned long` 类型 - `inet_ntoa...

    Delphi开发经验技巧宝典光盘源码

    - **0117**:整数与十六进制字符串之间的转换技巧。 - **0118**:整数与十六进制数值之间的转换技巧。 - **0119**:整数与字符串之间的转换技巧。 - **0120**:字符串与整数之间的转换技巧。 - **0121**:字符...

    ipv6技术详解

    IPv6技术的发展背景源自于1990年代初,随着互联网的迅速发展,IP地址资源变得日益紧张。在这一时期,互联网用户从大型主机逐渐转移到个人电脑(PC)、个人数字助理(PDA)、汽车、手机、家用电器以及无线传感器等...

    简易的C语言IP和校验程序

    根据给定的信息,本文将对一个简易的C语言IP地址处理及校验程序进行详细的解析。该程序的主要功能包括:接收二进制形式的输入,对其进行处理后输出对应的校验码。下面将从程序的工作原理、核心算法以及实现细节等...

    手稿_V1.032

    另外,`stoi`函数用于将字符串转换为整数,这在检查子串是否超过255时使用。 4. **IP地址的表示**:题目要求从一个只包含数字的字符串中恢复可能的IP地址。一个有效的IPv4地址由四个0-255之间的十进制数字组成,每...

    winsock 函数详解

    - **inet_addr()**:将点分十进制的IP地址转换为网络字节序的32位整数形式。 - **ioctlsocket()**:用于控制套接字的一些特殊行为。 - **listen()**:服务器端使用此函数监听连接请求。 - **ntohl()**/`ntohs()`:将...

    Ethernet_TCP-IP_Socket_MFC Doc

    1. **设置服务器 IP 地址**:通常使用 `inet_addr` 函数将字符串形式的 IP 地址转换为整数形式。 2. **创建服务器 Socket**:使用 `socket` 函数创建一个 Socket 描述符。 3. **绑定服务器 Socket**:使用 `bind` ...

    VLSM(可变长度子网掩码)的计算

    - **CIDR(无类别域间路由)**:这是一种新的IP地址分配方式,它取消了传统的A类、B类和C类地址的分类,采用更为灵活的子网掩码表示法,提高了IP地址的利用率。 #### 二、VLSM的应用场景 VLSM允许在同一主网络下...

    Python 面试题汇总及答案详解完整版

    10. **IP地址转整数**:通过将IP地址的每一部分看作一个整数,然后按字节相加,如IPv4地址"192.168.1.1"对应的整数是3232235777。 11. **Python递归最大层数**:通常默认为998层,可通过sys.setrecursionlimit()...

    正则表达式详解

    转换IP地址为数值,可以使用正则表达式匹配并提取各个部分,然后进行计算。例如:`/(\d+)\.(\d+)\.(\d+)\.(\d+)/g`,然后将每个匹配到的部分乘以对应的255的幂次再相加。 8. **其他常见正则表达式**: - 匹配中文...

Global site tag (gtag.js) - Google Analytics