socket编程之IP地址转换函数

1,087 阅读3分钟

IP地址转换函数

将字符串类型的IP地址转换成网络字节序整数型IP地址,或是将网络字节序IP地址转换成字符串类型的IP地址

image-20220522220359645.png

一、对以上示意图展开验证

 #include <arpa/inet.h>
 ​
 // 将字符串的IP地址转换成网络字节序的IP地址
 // af的取值有两种: AF_INET(IPv4)和AF_INET6(IPv6)
 // src 是要转换的IP地址(字符串)
 // 转换后的值会保存在dst中
 int inet_pton(int af, const char* src, void *dst);
 ​
 // 将网络字节序转换成字符串型IP地址
 // size是转换后数组的大小
 const char* inet_ntop(int af, const void *src, char *dst, socklen_t size);

1. 字符串型IP地址转换

 #include <stdio.h>
 #include <string.h>
 #include <arpa/inet.h>
 ​
 int main(void)
 {
     char ip[] = "2.3.4.5";
 ​
     //! 要将其转换成网络字节序的IP,然后将其保存在此地址结构中
     struct sockaddr_in server_addr;
     
     //! 第二个参数,传入(IP地址)数组的指针
     //! 第三个参数,保存到哪里
     inet_pton(AF_INET, ip, &server_addr.sin_addr.s_addr);
     //! 用16进制的方式将网络字节序的整型值打印出来
     printf("s_addr 网络字节序: %x\n", server_addr.sin_addr.s_addr);
     //! 以上是IP的网络字节序,那么主机字节序呢?
     printf("s_addr from net to host: %x\n", ntohl(server_addr.sin_addr.s_addr));
 ​
     //! IPv4以.隔开,中间的每一个数字都是字节保存的值
     //! 16进制两位占一个字节
     //! s_addr 网络字节序: 5040302: 这个就是网络字节序的大端字节序,低地址保存高位
     //! s_addr from net to host: 2030405: 变成了第一个字节05,这是小端字节序
 ​
 }

2. 网络字节序的IP怎么转换成字符串型IP

 #include <stdio.h>
 #include <string.h>
 #include <arpa/inet.h>
 ​
 int main(void)
 {
     char ip[] = "2.3.4.5";
     uint32_t ip_Int;
     char server_ip1[64]; //! 字符串IP
     char server_ip2[64]; //! 字符串IP
 ​
     //! 要将其转换成网络字节序的IP,然后将其保存在此地址结构中
     struct sockaddr_in server_addr;
     
     //! 第二个参数,传入(IP地址)数组的指针
     //! 第三个参数,保存到哪里
     inet_pton(AF_INET, ip, &server_addr.sin_addr.s_addr);
     //! 用16进制的方式将网络字节序的整型值打印出来
     printf("s_addr 网络字节序: %x\n", server_addr.sin_addr.s_addr);
     //! 以上是IP的网络字节序,那么主机字节序呢?
     ip_Int = ntohl(server_addr.sin_addr.s_addr);
     printf("s_addr from net to host: %x\n", ip_Int);
 ​
     //! IPv4以.隔开,中间的每一个数字都是字节保存的值
     //! 16进制两位占一个字节
     //! s_addr 网络字节序: 5040302: 这个就是网络字节序的大端字节序,低地址保存高位
     //! s_addr from net to host: 2030405: 变成了第一个字节05,这是小端字节序
 ​
     //! 其实这样写没意思,因为这个函数就是用来从网络字节序转换成字符串型IP地址的net to p
     inet_ntop(AF_INET, &server_addr.sin_addr.s_addr, server_ip1, 64);
     inet_ntop(AF_INET, &ip_Int, server_ip2, 64);
     printf("字符串(5040302大端字节序) server_ip: %s\n", server_ip1);
     printf("字符串(2030405小端字节序(主机)) server_ip: %s\n", server_ip2);
 }
 ​

image-20220523155026884.png

3. 监听本机所有IP地址

 htonl(INADDR_ANY); //服务器上有多个网卡
 #include <stdio.h>
 #include <string.h>
 #include <arpa/inet.h>
 ​
 int main(void)
 {
     char ip[] = "2.3.4.5";
     char server_ip[64]; //字符串型IP
     //! 要将其转换成网络字节序的IP,然后将其保存在此地址结构中
     struct sockaddr_in server_addr;
     struct sockaddr_in any_addr;
     char any[64];
     //! 第二个参数,传入(IP地址)数组的指针
     //! 第三个参数,保存到哪里
     inet_pton(AF_INET, ip, &server_addr.sin_addr.s_addr);
     //! 用16进制的方式将网络字节序的整型值打印出来
     printf("s_addr 网络字节序: %x\n", server_addr.sin_addr.s_addr);
     //! 以上是IP的网络字节序,那么主机字节序呢?
     printf("s_addr from net to host: %x\n", ntohl(server_addr.sin_addr.s_addr));
 ​
     //! IPv4以.隔开,中间的每一个数字都是字节保存的值
     //! 16进制两位占一个字节
     //! s_addr 网络字节序: 5040302: 这个就是网络字节序的大端字节序,低地址保存高位
     //! s_addr from net to host: 2030405: 变成了第一个字节05,这是小端字节序
 ​
     inet_ntop(AF_INET, &server_addr.sin_addr.s_addr, server_ip, 64);
     printf("字符串server_ip: %s\n", server_ip);
 ​
 ​
     //! INADDR_ANY
     printf("INADDR_ANY: %d\n", INADDR_ANY);
     any_addr.sin_addr.s_addr = INADDR_ANY;
     inet_ntop(AF_INET, &any_addr.sin_addr.s_addr, any, 64);
     printf("INADDR_ANY(字符串IP): %s\n", any);
     return 0;
 }

image-20220523210551815.png