Linux网络编程:IP地址字符串格式与in_addr格式的相互转换

目录

1.字符串格式转in_addr格式

2.in_addr格式转字符串格式

3.补充:IPv4地址和IPv6地址的结构体


在基于IPv4/IPv6的Socket网络编程中,通常会使用sockaddr_in/sockaddr_in6结构体进行网络通信,sockaddr_in结构体中的成员sin_addr表示32位的IP地址,sockaddr_in6结构体中的成员sin6_addr表示128位的IP地址,这些都是in_addr格式的IP地址。但是我们通常使用点分十进制表示IP地址,而使用in_addr格式的IP地址比较复杂。

因此操作系统为我们提供了IP地址转换函数:支持IP地址在点分十进制字符串格式和in_addr格式的IP地址之间相互转换。

1.字符串格式转in_addr格式

int inet_pton(int af, const char *src, void *dst);

#include <arpa/inet.h>

int inet_pton(int af, const char *src, void *dst);

af:地址族,指定要转换的地址类型(AF_INET表示IPv4地址,AF_INET6表示IPv6地址)

src:指向包含点分十进制格式IP地址字符串的指针

dst:指向转换成功后存储IP地址的缓冲区的指针(IPv4地址下为struct in_addr结构体,IPv6地址下位struct in6_addr结构体)

返回值:成功返回1,失败返回-1并设置errno错误码(如果src不是有效的IP地址,返回0)

示例代码(IPv4地址):

#include <iostream>
#include <arpa/inet.h>
//IPv4地址
void test()
{
    //int inet_pton(int af, const char *src, void *dst);
    const char* ip_str="127.0.0.1";//字符串格式IP地址
    struct in_addr ip_bin;//in_addr格式IP地址
    int result=inet_pton(AF_INET,ip_str,&ip_bin);
    if(result==1)
        std::cout<<"转换成功,in_addr格式IP地址为:"<<ip_bin.s_addr<<std::endl;
    else if(result==0)
        std::cout<<"无效IP地址"<<std::endl;
    else
        std::cerr<<"转换失败"<<std::endl;
}
int main()
{
    test();
    return 0;
}

2.in_addr格式转字符串格式

const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)

#include <arpa/inet.h>

const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)

af:地址族,指定要转换的地址类型(AF_INET表示IPv4地址,AF_INET6表示IPv6地址)

src:指向存储网络字节序IP地址的缓冲区(IPv4地址下是指向struct in_addr的指针,IPv6地址下是指向struct in6_addr的指针)

dst:指向存储点分十进制字符串形式的IP地址缓冲区的指针

cnt:dst缓冲区的大小,单位为字节

返回值:成功返回只想dst的指针,失败返回NULL并设置errno错误码

示例代码:

//IPv4地址
void test()
{
    //const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
    struct in_addr ip_bin;
    ip_bin.s_addr=0x01020304;//假设存在一个in_addr格式的IPv4地址:1.2.3.4
    ip_bin.s_addr=htonl(ip_bin.s_addr);//要先将主机字节序IP地址转换为网络字节序IP地址
    char ip_str[1024];

    const char* result=inet_ntop(AF_INET,&ip_bin,ip_str,sizeof(ip_str));
    if(result==nullptr)
        std::cout<<"转换失败"<<std::endl;
    else   
        std::cout<<"转换成功,点分十进制字符串格式IP地址为:"<<ip_str<<std::endl;

}
int main()
{
    test();
    return 0;
}

3.补充:IPv4地址和IPv6地址的结构体

IPv4地址结构体

struct sockaddr_in {
    sa_family_t sin_family;  // 地址族,通常为 AF_INET 表示 IPv4
    uint16_t sin_port;       // 端口号,使用网络字节序
    struct in_addr sin_addr; // IPv4 地址,使用网络字节序
    char sin_zero[8];        // 填充字段,用于使结构体大小与 sockaddr 一致
};

struct in_addr {
    uint32_t s_addr;  // IPv4地址,以网络字节序存储
};

IPv6地址结构体 

struct sockaddr_in6 {
    sa_family_t sin6_family;   // 地址族,通常为 AF_INET6 表示 IPv6
    uint16_t sin6_port;        // 端口号,使用网络字节序
    uint32_t sin6_flowinfo;    // 流信息,通常设置为0
    struct in6_addr sin6_addr; // IPv6 地址,使用网络字节序
    uint32_t sin6_scope_id;    // 作用域标识,用于链路本地地址等
};

struct in6_addr {
    uint8_t s6_addr[16];  // IPv6地址,以网络字节序存储
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南林yan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值