Windows 下IP点分十进制和网络字节序的转换

本文介绍了一个用于IP地址转换的C语言实现,包括将点分十进制字符串转换为网络字节序的函数__inet_aton,以及反向转换的函数__inet_ntoa。通过示例代码展示了如何使用这两个函数。


博客http://blog.youkuaiyun.com/unimen/article/details/6844456给出相关实现,我根据C库的代码,也给出一个:

[cpp]  view plain copy
  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7.   
  8. /* 
  9.  * Ascii internet address interpretation routine. 
  10.  * The value returned is in network order. 
  11.  */  
  12. unsigned int  
  13. __inet_aton(const char *cp)  
  14. {  
  15.     unsigned int val = 0;  
  16.     unsigned int tmp = 0;  
  17.     char c;  
  18.     int base = 10;  
  19.     int shift = 32;  
  20.   
  21.     c = *cp;  
  22.     for (;;) {//可以给出一个任意长度的字符串;  
  23.         tmp = 0;  
  24.         for (;;) {//获得'.'分割的每一个字符串的数值;  
  25.             if (isdigit(c)) {  
  26.                 tmp = (tmp * base) + (c - '0');  
  27.                 c = *++cp;  
  28.             } else break;  
  29.         }  
  30.   
  31.         shift -= 8;  
  32.         tmp <<= shift;  
  33.         val += tmp;   
  34.           
  35.         if (c == '.') {  
  36.             c = *++cp;  
  37.         } else  
  38.             break;  
  39.     }  
  40.   
  41.     /* 
  42.      * Check for trailing characters. 
  43.      */  
  44.     if (c != '\0' && (!isspace(c)))  
  45.         goto ret_0;  
  46.   
  47.     return (htonl (val));//返回网络字节序  
  48. ret_0:  
  49.     return (0);  
  50. }  
  51.   
  52. /* The interface of this function is completely stupid, it requires a 
  53.    static buffer.  We relax this a bit in that we allow one buffer for 
  54.    each thread.  */  
  55. static char buffer[18];//作为库函数,正式这个函数不能重入的原因;  
  56. char *  
  57. __inet_ntoa (unsigned int in)  
  58. {  
  59.   unsigned char *bytes = (unsigned char *) ∈  
  60.   snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",  
  61.           bytes[0], bytes[1], bytes[2], bytes[3]);//网络字节序是小端表示,第一个是byte[0];  
  62.   
  63.   return buffer;  
  64. }  
  65.   
  66. int main()  
  67. {  
  68.     printf("ip :%lu\n",__inet_aton("192.168.1.105 "));    
  69.     printf("str:%s\n",__inet_ntoa(__inet_aton("192.168.1.105")));  
  70.     return 0;     
  71. }  
也可以使用Windows socket API
(1)inet_ntoa() //将网络字节序转换为十分点进制字符串
(2)inet_addr() //将 十分点进制字符串转换为网络字节序
例:
unsigned  long  addr=inet_addr("127.0.0.1");
char * Apddr=inet_ntoa(*(in_addr*)& addr);

in_addr 为网络地址结构体大小为4个字节



### 点分十进制表示法在网络字节序主机字节序中的关系 点分十进制表示法是一种用于描述 IPv4 地址的方式,通常由四个以圆割的十进制数构成,每个数代表一个字节(8位)。这种表示方法便于人类阅读理解。然而,在计算机内部存储网络传输过程中,IPv4 地址会受到字节序的影响。 #### 1. **网络字节序** 网络字节序是指在数据通过网络传输时所使用的字节顺序标准。根据 UDP/TCP/IP 协议的规定,网络字节序采用大端字节序(Big Endian),这意味着多字节数值的最高有效字节被放置在最低地址位置[^2]。因此,当一个整型数值(如 IPv4 地址)在网络上进行传输时,其高位字节会被优先发送并存储到内存的低地址处。 例如,假设有一个 IPv4 地址 `0xC0A80101`(即 192.168.1.1 的十六进制形式),在网络字节序下,它的存储顺序如下: | 字节 | 值 | |------|-------| | 第一字节 | C0 | | 第二字节 | A8 | | 第三字节 | 01 | | 第四字节 | 01 | 将其转换点分十进制表示法时,按照从高到低的顺序依次提取各字节的值,并用`.`连接起来,最终得到的结果是 `192.168.1.1`。 --- #### 2. **主机字节序** 主机字节序指的是不同架构的处理器在其本地内存中存储多字节数值的方式。常见的两种主机字节序别是小端字节序(Little Endian)大端字节序(Big Endian)。现代大多数 x86 架构的 CPU 使用的是小端字节序,而某些 RISC 处理器则可能使用大端字节序。 如果主机字节序为小端,则上述相同的 IPv4 地址 `0xC0A80101` 在内存中的实际排列将是反向的: | 字节 | 值 | |------|-------| | 第一字节 | 01 | | 第二字节 | 01 | | 第三字节 | A8 | | 第四字节 | C0 | 在这种情况下,如果不经过任何调整就直接将此地址写入缓冲区或传送到网络接口卡上,那么接收方可能会误解该地址的实际含义。为了确保兼容性一致性,程序设计者通常会在发送前调用特定函数来完成必要的字节序转换操作,比如 `htonl()` `ntohl()` 函数别用来实现主机字节序网络字节序以及相反方向上的变换过程[^2]。 --- #### 3. **点分十进制与两者之间的联系** 由于点分十进制本质上是对二进制或者十六进制 IP 地址的一种直观表达手段,所以在讨论它同这两种字节序列之间存在何种关联之前,我们需要明确一——无论是在哪种环境下呈现出来的形式都应该是完全一致的。换句话说,不管原始数据最初是以什么样的次序存在于物理介质之上,只要最后能够正确解析出来形成符合预期模式的一串字符即可满足需求。 具体而言,当我们试图打印某个已经处于某种固定状态下的IP变量至屏幕上面去供用户查看之时,往往需要借助诸如C语言里的printf族成员之一sprintf这样的工具来进行格式化输出作业。此时需要注意的一个重要环节就是如何准确无误地定位每一个独立组成部的位置信息以便于后续拼接动作得以顺利开展下去。这里可以参考前面提到过的那个例子当中给出的具体做法:定义了一个名为union类型的结构体对象x之后再利用其中嵌套着的部字段名称s1~s4逐一访问目标实体各个部的内容从而达到目的[^3]。 ```c #include <stdio.h> #include <string.h> union IPNode { unsigned int addr; struct { unsigned char s1; unsigned char s2; unsigned char s3; unsigned char s4; }; }; char* my_DotDec(unsigned int ip, char *buffer) { union IPNode x; x.addr = ip; sprintf(buffer, "%d.%d.%d.%d", x.s4, x.s3, x.s2, x.s1); return buffer; } int main() { unsigned int ip = 0xC0A80101; // Example IP address in network byte order char buffer[16]; printf("%s\n", my_DotDec(ip, buffer)); // Output should be "192.168.1.1" return 0; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值