02 inet_aton, inet_ntoa, inet_addr, inet_network函数

本文详细解析了在网络编程中,如何利用Linux提供的inet_aton、inet_ntoa、inet_addr及inet_network等函数,高效实现网络字节与本地字节之间的转换。文章通过具体示例代码展示了各函数的使用方法及其返回值,特别强调了inet_aton函数的重要性。

在网络编程中, 经常会将网络字节转为本地字节或者将本地字节转为网络字节, 但是如果每次我们都是都通过htonl, ntohl函数需要将10进制转为整数, 甚至还用将字符串转为整数, 再转为网络字节, 或者反过来都是很麻烦的. 还好linux都是提供很方便的函数让两者之间进行转换.


转换函数

linux提供了多种函数满足我们任何转换的需求, 这都是inet_xxx族系列

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

int inet_aton(const char *ip, struct in_addr *inp);	// 本地转网络

char * inet_ntoa(struct in_addr inp);	// 网络转本地

in_addr_t inet_addr(const char *ip);	// 返回网络字节

in_addr_t inet_network(const char *ip);	// 返回本地字节

接下来我们来在分析一下这几个函数


1. inet_aton函数

将点分十进制IP转化为网络字节序存放在inp中, 并返回该网络字节序对应的整数.

int inet_aton(const char *ip, struct in_addr *inp);	

失败 : 返回0.

成功 : 返回IP对应的网络字节序的数.


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>

// 传入 127.0.0.1
int main(int argc, char *argv[])
{
	if(argc != 2)
		exit(-1);

	struct in_addr addr;
	if(inet_aton(argv[1], &addr) == 0)
		exit(-1);
	printf("0x%08x\n", addr.s_addr); // 0x0100007f
 
    exit(EXIT_SUCCESS);
}

2. inet_ntoa函数

将一个32位网络字节序的二进制IP地址转换成相应的点分十进制的IP地址.

char *inet_ntoa(struct in_addr inp);

失败 : 返回NULL.

成功 : 返回字符串指针.

注意 : 该函数不是线程安全函数, 不可重入. 因为不同线程调用会覆盖掉其他线程的缓冲区.


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char *argv[])
{
	struct in_addr net_addr;
	net_addr.s_addr = 0x0100007f;	// 127.0.0.1
	char *host_addr;

	host_addr = inet_ntoa(net_addr);
	printf("%s\n", host_addr);	// 127.0.0.1
 
    exit(EXIT_SUCCESS);
}

3. inet_addr函数

将一个点分十进制转换网络字节序IP.

in_addr_t inet_addr(const char *ip);

失败 : 返回INADDR_NONE. 部分手册上返回的是-1, 这个问题与inet_network一样了.

成功 : 返回网络字节IP.


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

// 输入 127.0.0.1
int main(int argc, char *argv[])
{
    in_addr_t addr;

    addr = inet_addr(argv[1]);
    printf("0x%08x\n", addr);	// 0x0100007f

    exit(EXIT_SUCCESS);
}

4. inet_network函数

将点分十进制IP转化为主机字节序

in_addr_t inet_network(const char *ip);

失败 : 返回-1.

成功 : 返回主机对应的数.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// 输入 127.0.0.1
int main(int argc, char *argv[])
{
	in_addr_t addr;

	addr = inet_network(argv[1]);
	printf("0x%08x\n", addr);	// 0x7f000001
 
    exit(EXIT_SUCCESS);
}

该函数在某些情况下并不正确, 如果IP地址是255.255.255.255返回的则是0xffffffff, 转为十进制就是-1. 分不清出-1表示的是错误的返回值还是IP地址. 可以使用inet_pton()inet_ntop()函数来代替, 这里就不详细的分析了, 有兴趣的可以自己查一下.


完整代码 : inet族


总结

本节分析了4个函数, 重点需要掌握的是inet_aton函数.

  • 4个函数使用, 以及返回值
  • inet_network返回值的问题
  • inet_ntoa并不是线程安全的函数
`inet_aton` 和 `inet_ntoa` 是用于在 IP 地址的点分十进制字符串表示形式和 32 位二进制整数之间进行转换的标准函数,常用于网络编程中处理 IPv4 地址。这两个函数属于 POSIX 标准库中的 `<arpa/inet.h>` 头文件(在 Linux/Unix 系统中)。 ### `inet_aton` 该函数将 IPv4 地址从字符串表示形式(如 `"192.168.1.1"`)转换为网络字节序的 32 位二进制整数(即 `in_addr_t` 类型)。其原型如下: ```c int inet_aton(const char *cp, struct in_addr *inp); ``` - `cp`:指向一个以点分十进制格式表示的 IPv4 地址字符串。 - `inp`:指向一个 `struct in_addr` 结构体的指针,用于存储转换后的二进制地址。 返回值: - 成功时返回 1; - 输入无效则返回 0。 示例代码: ```c #include <stdio.h> #include <arpa/inet.h> int main() { struct in_addr ip; int success = inet_aton("192.168.1.1", &ip); if (success) { printf("Binary representation: %u\n", ip.s_addr); } else { printf("Invalid address.\n"); } return 0; } ``` ### `inet_ntoa` 该函数的作用与 `inet_aton` 相反,它将网络字节序的 32 位 IPv4 地址转换为点分十进制字符串形式。其原型如下: ```c char *inet_ntoa(struct in_addr in); ``` - `in`:包含网络字节序的 IPv4 地址的 `struct in_addr` 结构体。 返回值是一个静态分配的字符串,表示转换后的 IP 地址[^1]。 示例代码: ```c #include <stdio.h> #include <arpa/inet.h> int main() { struct in_addr ip; inet_aton("192.168.1.1", &ip); char *ip_str = inet_ntoa(ip); printf("IP Address: %s\n", ip_str); return 0; } ``` ### 注意事项 - `inet_ntoa` 返回的是一个静态缓冲区的指针,因此在多线程环境中或多次调用时需要注意数据覆盖问题。 - 这两个函数仅支持 IPv4 地址。对于 IPv6 地址,应使用 `inet_pton` 和 `inet_ntop` 函数来替代。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值