inet_ntop()、inet_pton()、inet_addr()、inet_ntoa()函数之间的关系

- emmmmm,先看这张图来理解,知道这些函数的作用

在这里插入图片描述

1. inet_pton()源码

int inet_pton(int family, const char *strptr, void *addrptr)
{
    if (family == AF_INET) {
	    struct in_addr  in_val;
		if (inet_aton(strptr, &in_val)) {
		    memcpy(addrptr, &in_val, sizeof(in_val));
		    return (1);
		}
	}
	errno = EAFNOSUPPOPT;
	return (-1);
}

2. inet_ntop()源码

const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len)
{
	const u_char *p = (const u_char*)addrptr;
	if (family == AF_INET) {
		char temp[INET_ADDRSTRLEN];
		snprintf(temp, sizeof(temp), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
		if (strlen(temp) >= len) {
		    errno = ENOSPC;
		    rturn (NULL);
		}
		strcpy(strptr, temp);
		return (strptr);
	}
	errno = EAFNOSUPPOPT;
	return (NULL);
}

3. inet_addr()

转换网络主机地址(点分十进制)为网络字节序二进制值,如果参数 char *cp 无效则返回-1(INADDR_NONE),但这个函数有个缺点:在处理地址为255.255.255.255时也返回-1,虽然它是一个有效地址,但inet_addr()无法处理这个地址。

in_addr_t inet_addr(const char *cp);

4. inet_ntoa()------->静态函数

inet_ntoa()函数转换网络字节序地址->标准的点分十进制地址。该函数返回值指向保存点分十进制的字符串地址的指针,该字符串的空间为静态分配 的,所以在第二次调用这个函数时,意味着上一次调用并保存的结果将会被覆盖(重写)。so creazy!!!

char *inet_ntoa(struct in_addr in);

好了那就来证实一下,inet_ntoa()的静态返回值吧!!

char *add1,add2;
src.sin_addr.s_addr  =  inet_addr("192.168.1.123");
add1 =inet_ntoa(src.sin_addr);                  
src.sin_addr.s_addr = inet_addr("192.168.1.124");
add2 = inet_ntoa(src.sin_addr);
 
printf("a1:%s\n",add1);
printf("a2:%s\n",add2);

最终的printf结果是:
a1:192.168.1.124
a2:192.168.1.124

- 这样来看的话,我认为如果有需要最好是用inet_pton()、inet_ntop()代替inet_ntoa()、inet_addr().

用
inet_pton(AF_INET, cp, &src.sin_addr);
代替
src.sin_addr.s_addr = inet_addr(cp);
用
char str[INET_ADDRATRLEN];
ptr = inet_ntop(AF_INET, &src.sin_addr, str, sizeof(str));
代替
ptr = inet_ntoa(src.sin_addr);

 (478条消息) inet_ntop()、inet_pton()、inet_addr()、inet_ntoa()函数之间的关系_lockin.的博客-优快云博客_inet_addr

<think>嗯,用户想了解inet_ntop函数的详细用法和说明。首先,我需要回忆这个函数作用。它应该是用于将IPv4或IPv6地址从二进制格式转换成点分十进制或冒号分隔的字符串形式。对吗?是的,没错,因为网络编程中常常需要处理地址的转换,比如从struct in_addr或者struct in6_addr转换成人可读的字符串。 接下来,用户需要API文档,所以我要确认函数的参数和返回值。函数原型应该是const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)。参数af是地址族,比如AF_INET或AF_INET6,src指向包含二进制地址的结构体,dst是存储结果的缓冲区,size是缓冲区的大小。返回值成功时返回dst的指针,失败返回NULL,并设置errno。对吧?是的,我记得没错。 然后用户需要示例代码。我需要提供IPv4和IPv6的例子。比如,对于IPv4,创建一个struct sockaddr_in结构体,填充sin_addr,然后用inet_ntop转换。同样,IPv6的话用struct sockaddr_in6和sin6_addr。注意缓冲区大小,IPv4至少需要INET_ADDRSTRLEN(16字节),IPv6需要INET6_ADDRSTRLEN(46字节)。确保示例代码正确,不要有语法错误。 还要注意错误处理,检查返回值是否为NULL,处理可能的错误情况,比如地址族不支持。可能出现的错误是EAFNOSUPPORT,如果af参数无效的话。此外,缓冲区太小的话会返回NULL,errno设置为ENOSPC,所以需要确保缓冲区足够大。 用户提供的引用中有关于socket文件描述符和getsockopt/setsockopt的内容,虽然和inet_ntop直接关系不大,但可能用户是在网络编程的上下文中使用这个函数,比如在处理socket地址时需要转换格式。所以可能需要提到和这些函数一起使用的场景,比如在服务器端获取客户端地址后转换成可读字符串。 另外,用户提到参数处理在策略模式的execute方法中完成,可能需要注意在代码示例中参数的正确传递,比如地址族参数是否正确,结构体是否正确初始化。错误处理部分可以参考引用中的错误处理部分,确保示例中有基本的错误检查。 最后,生成相关问题,需要围绕inet_ntop的用途、参数、错误处理,以及相关函数inet_pton,可能的应用场景,和IPv6处理等。确保问题有针对性,帮助用户深入理解。 总结一下,回答的结构应该是先介绍函数用途,参数说明,返回值,错误处理,示例代码,注意事项,相关问题。需要引用用户提供的资料中相关的部分,比如socket文件描述符的使用,或者错误处理的方法。但根据用户提供的引用,可能引用[^2]中的setsockopt或getsockopt,不过和inet_ntop关系不大,可能不需要直接引用。但用户提到引用[2]中的socket函数,所以可以提到在处理socket地址时使用inet_ntop转换地址,比如在accept后获取客户端的地址信息,转换成字符串记录日志等场景。</think>### inet_ntop 函数说明 #### 功能 `inet_ntop` 用于将二进制格式的 IPv4 或 IPv6 地址转换为人类可读的字符串格式(如 `192.168.1.1` 或 `2001:db8::1`)。它是 `inet_ntoa` 的替代品,支持 IPv6 且线程安全。 --- #### 函数原型 ```c #include <arpa/inet.h> const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); ``` --- #### 参数说明 1. **`af`** - 地址族,取值为 `AF_INET`(IPv4)或 `AF_INET6`(IPv6)。 2. **`src`** - 指向包含二进制地址的结构体指针。 - IPv4:`struct in_addr`(如 `sockaddr_in.sin_addr`) - IPv6:`struct in6_addr`(如 `sockaddr_in6.sin6_addr`) 3. **`dst`** - 存储转换后字符串的缓冲区指针。 4. **`size`** - 缓冲区 `dst` 的长度。IPv4 至少需 `INET_ADDRSTRLEN`(16 字节),IPv6 需 `INET6_ADDRSTRLEN`(46 字节)。 --- #### 返回值 - 成功:返回 `dst` 指针。 - 失败:返回 `NULL`,并设置 `errno`(如地址族无效或缓冲区不足)。 --- #### 错误处理 | 错误码 | 原因 | |----------------|-------------------------| | `EAFNOSUPPORT` | `af` 不是 `AF_INET`/`AF_INET6` | | `ENOSPC` | `dst` 缓冲区空间不足 | --- #### 示例代码 ##### IPv4 地址转换 ```c #include <arpa/inet.h> #include <stdio.h> int main() { struct sockaddr_in sa; char ip_str[INET_ADDRSTRLEN]; sa.sin_addr.s_addr = inet_addr("192.168.1.1"); if (inet_ntop(AF_INET, &(sa.sin_addr), ip_str, INET_ADDRSTRLEN) == NULL) { perror("inet_ntop failed"); return 1; } printf("IPv4 Address: %s\n", ip_str); // 输出: 192.168.1.1 return 0; } ``` ##### IPv6 地址转换 ```c #include <arpa/inet.h> #include <stdio.h> int main() { struct sockaddr_in6 sa6; char ip6_str[INET6_ADDRSTRLEN]; inet_pton(AF_INET6, "2001:db8::1", &(sa6.sin6_addr)); if (inet_ntop(AF_INET6, &(sa6.sin6_addr), ip6_str, INET6_ADDRSTRLEN) == NULL) { perror("inet_ntop failed"); return 1; } printf("IPv6 Address: %s\n", ip6_str); // 输出: 2001:db8::1 return 0; } ``` --- #### 注意事项 1. **缓冲区安全**:始终使用 `INET_ADDRSTRLEN` 或 `INET6_ADDRSTRLEN` 定义缓冲区大小。 2. **线程安全**:与 `inet_ntoa` 不同,`inet_ntop` 不依赖静态存储区。 3. **反向操作**:使用 `inet_pton` 将字符串转换为二进制地址。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值