函数inet_addr和inet_aton

本文详细介绍了IP地址在不同字节顺序间的转换方法,包括inet_addr、inet_aton等函数的应用及区别,强调了网络字节顺序的重要性。
 

inet_addr 将"数字+句点"的格式的IP地址转换到unsigned long中,返回值已经是按照网络字节顺序的
相反inet_ntoa把类型为struct in_addr的数据转化为"数字+句点"的形式的字符串
typedef u_int32_t in_addr_t;
struct in_addr
{
       in_addr_t s_addr;
};

本机字节顺序与网络字节顺序的转换
#include <arpa/inet.h>
htons  ------"host to network short"
htonl   -------"host to network long"
ntohs  -------"network to host short"
ntohl   -------"network to host long"
*注意:在你的数据放到网络上的时候,确信它是网络字节顺序
网络字节顺序(大端字节)和x86机器字节顺序(小端字节)
eg:0X3132  在x86上显示21  在网络传输中为12

inet_addr返回的整数形式是网络字节序,而inet_network返回的整数形式是主机字节序。他俩都有一个小缺陷,
那就是当IP是255.255.255.255时,这两个函数会认为这是个无效的IP地址,这是历史遗留问题,其实在目前大部
分的路由器上,这个255.255.255.255的IP都是有效的。
inet_aton函数和上面这俩个函数的区别就是在于他认为255.255.255.255是有效的,他不会冤枉这个看似特殊的IP地址。对了,inet_aton函数返回的是网络字节序的IP地址。

综上所述,应该使用inet_aton和inet_ntoa这一对函数。


资料:

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

typedef uint32_t in_addr_t;

int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(
const char *cp);
in_addr_t inet_network(
const char *cp);
char *inet_ntoa(struct in_addr in);
struct in_addr inet_makeaddr(int net, int host);
in_addr_t inet_lnaof(
struct in_addr in);
in_addr_t inet_netof(
struct in_addr in);


 

// Internet address.
struct in_addr {
        union {
                
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                
struct { u_short s_w1,s_w2; } S_un_w;
                u_long S_addr; 
/* port in network byte order */
        } S_un;
#define s_addr  S_un.S_addr
};
// Socket address, internet style.
struct sockaddr_in {        // struct sockaddr的一种特殊形式
        short            sin_family;    /* address family: AF_INET */
        u_short        sin_port;        
/* port in network byte order */
        
struct in_addr sin_addr;        /* port in network byte order */
        
char            sin_zero[8];    /* 8 byte pad */
};
// Structure used by kernel to store most addresses.
struct sockaddr {
        u_short sa_family; 
/* address family */
        
char    sa_data[14]; /* up to 14 bytes of direct address */
};

struct in_addr {
    unsigned 
long int s_addr;
}
<think>好的,用户之前已经询问过关于htonl、htons等字节序转换函数的用法,现在他们又提到了inet_aton函数。我需要确定用户具体想了解哪些函数,以及他们可能的使用场景。 首先,用户提到的inet_aton属于地址转换函数,用于将点分十进制的IP地址字符串转换为网络字节序的二进制形式。这类函数网络编程中常用于处理IP地址,属于基础但重要的部分。考虑到用户之前的问题是关于字节序转换,现在转向地址转换,可能需要补充这部分知识,帮助用户全面理解网络编程中的数据转换。 接下来,我需要回顾常见的地址转换函数,如inet_atoninet_addrinet_ntoa,以及更现代的inet_ptoninet_ntop。用户可能在使用这些函数时遇到问题,比如兼容性、线程安全,或者对IPv6的支持。需要详细解释每个函数的用法、参数、返回值以及注意事项,尤其是过时的函数inet_addrinet_ntoa的安全问题。 用户可能没有直接提到,但潜在的需求可能是如何在不同的IP地址格式之间正确转换,确保网络程序在不同环境下的稳定性兼容性。例如,使用inet_pton替代过时的函数,处理IPv6地址,或者线程安全的问题。需要强调推荐使用inet_ptoninet_ntop,因为它们支持IPv6并且更安全。 另外,用户可能对示例代码感兴趣,特别是如何在实际代码中使用这些函数。例如,将字符串"192.168.1.1"转换为struct in_addr,或者处理错误情况。需要提供具体的代码片段,并指出常见错误,比如未检查返回值导致的问题。 最后,总结部分要明确各个函数的适用场景,强调最佳实践,比如优先使用inet_pton,避免使用已被废弃的函数,并注意线程安全。这有助于用户做出正确的选择,避免潜在的bug兼容性问题。</think>好的!`inet_aton` 是网络编程中用于 **IP地址字符串与二进制格式相互转换** 的核心函数之一,常与 `inet_ntoa`、`inet_addr`、`inet_pton`、`inet_ntop` 等函数配合使用。以下是详细解析: --- ### **一、核心函数对比** | 函数名称 | 功能描述 | 输入类型 | 输出类型 | 线程安全 | IPv6支持 | 推荐指数 | |------------------|-----------------------------------|---------------|---------------|----------|----------|----------| | `inet_aton()` | 字符串IPv4 → 网络字节序二进制 | `const char*` | `struct in_addr` | 否 | ❌ | ★★☆☆☆ | | `inet_addr()` | 字符串IPv4 → 32位整数(已过时) | `const char*` | `in_addr_t` | 否 | ❌ | ★☆☆☆☆ | | `inet_ntoa()` | 网络字节序二进制 → 字符串IPv4 | `struct in_addr` | `char*` | 否 | ❌ | ★★☆☆☆ | | `inet_pton()` | 字符串IP → 二进制(支持IPv4/IPv6) | `int af` | `void*` | 是 | ✅ | ★★★★★ | | `inet_ntop()` | 二进制 → 字符串(支持IPv4/IPv6) | `int af` | `char*` | 是 | ✅ | ★★★★★ | --- ### **二、函数详解与代码示例** #### 1. **`inet_aton()`(ASCII to Network)** - **功能**:将点分十进制IPv4地址(如 `"192.168.1.1"`)转换为 `struct in_addr`(网络字节序) - **参数**: ```c int inet_aton(const char *cp, struct in_addr *inp); ``` - `cp`:输入字符串(如 `"192.168.1.1"`) - `inp`:输出二进制地址 - **返回值**:成功返回 `1`,失败返回 `0` - **示例**: ```cpp #include <arpa/inet.h> struct in_addr addr; if (inet_aton("192.168.1.1", &addr)) { printf("Binary IP: 0x%08x\n", addr.s_addr); } ``` #### 2. **`inet_ntoa()`(Network to ASCII)** - **功能**:将 `struct in_addr` 转换为点分十进制字符串 - **注意**:返回静态缓冲区,**非线程安全** - **示例**: ```cpp struct in_addr addr; addr.s_addr = htonl(0xC0A80101); // 192.168.1.1 char *ip_str = inet_ntoa(addr); // 返回静态内存指针 printf("IP String: %s\n", ip_str); ``` #### 3. **`inet_pton()`(Presentation to Network)** - **功能**:通用IP地址转换(支持IPv4/IPv6) - **参数**: ```c int inet_pton(int af, const char *src, void *dst); ``` - `af`:地址族(`AF_INET` 或 `AF_INET6`) - `src`:输入字符串(如 `"2001:db8::1"`) - `dst`:输出二进制地址(`struct in_addr` 或 `struct in6_addr`) - **示例**: ```cpp struct sockaddr_in6 ipv6_addr; if (inet_pton(AF_INET6, "2001:db8::1", &ipv6_addr.sin6_addr) == 1) { // 转换成功 } ``` #### 4. **`inet_ntop()`(Network to Presentation)** - **功能**:通用二进制地址转字符串(支持IPv4/IPv6) - **参数**: ```c const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); ``` - `size`:目标缓冲区大小(IPv4至少16字节,IPv6至少46字节) - **示例**: ```cpp struct in_addr addr; char ip_str[INET_ADDRSTRLEN]; // 专门用于IPv4的缓冲区 inet_ntop(AF_INET, &addr, ip_str, INET_ADDRSTRLEN); ``` --- ### **三、关键注意事项** #### 1. **`inet_addr()` 的缺陷** - 无法区分 `"0.0.0.0"` 错误返回值 `INADDR_NONE`(均为 `0xFFFFFFFF`) - **已过时**,建议用 `inet_aton()` 或 `inet_pton()` 替代 #### 2. **线程安全问题** - `inet_ntoa()` 使用静态缓冲区,多线程时需加锁 - **推荐优先使用 `inet_ntop()`** #### 3. **IPv6兼容性** - 使用 `inet_pton(AF_INET6, ...)` `inet_ntop(AF_INET6, ...)` 处理IPv6地址 #### 4. **缓冲区大小** - 定义缓冲区时使用标准常量: ```cpp #define INET_ADDRSTRLEN 16 // IPv4字符串最大长度 #define INET6_ADDRSTRLEN 46 // IPv6字符串最大长度 ``` --- ### **四、错误处理模板** ```cpp // IPv4转换示例 struct in_addr addr; const char *ip_str = "10.20.30.40"; if (inet_pton(AF_INET, ip_str, &addr) != 1) { perror("无效的IPv4地址"); exit(EXIT_FAILURE); } // 反向转换 char result_str[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &addr, result_str, INET_ADDRSTRLEN)) { perror("转换失败"); exit(EXIT_FAILURE); } ``` --- ### **五、总结** - **优先使用**:`inet_pton()` `inet_ntop()`(线程安全、支持IPv6) - **避免使用**:`inet_addr()` `inet_ntoa()`(过时、不安全) - **核心场景**: - 配置服务器监听地址时解析 `"0.0.0.0"` - 日志系统中将二进制IP转换为可读字符串 - 处理用户输入的IP地址时验证格式 这些函数网络编程中处理IP地址的基础工具,正确使用可有效避免地址解析错误安全性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值