当前位置: 代码迷 >> 综合 >> C++ socket IP int to string 自己实现 inet_ntop
  详细解决方案

C++ socket IP int to string 自己实现 inet_ntop

热度:80   发布时间:2023-09-18 13:29:58.0

在这之前,先来理清下大小端存储的区别,一般用的 intel x86 架构都是小端的机器。小端指低地址存放低位数据,高地址存放高位数据;而大端反之,低地址存放高位数据。

下面的例子一目了然。

1. 小端 ? "192.168.1.1" 字符串转成整型为 

[            1           ]             0x7ffeefbff493

[            1           ]             0x7ffeefbff492

[          168        ]             0x7ffeefbff491

[          192        ]             0x7ffeefbff490

16885952 (unsigned int)

 

2. 大端 ? "192.168.1.1" 字符串转成整型为 

[          192        ]             0x7ffeefbff493

[          168        ]             0x7ffeefbff492

[            1           ]             0x7ffeefbff491

[            1           ]             0x7ffeefbff490

= 3232235777 (unsigned int)

?? TCP/IP 协议约定先到达的数据当作高地址来存放,而 socket 字节流发送出去是先送出低地址数据的,这就意味着我们低地址需要存放高位的数据,也就是大端的形式。所以即使转换成字节流,也需要系统提供的 htonl 将小端顺序化成大端。

 

对于 IP 整数值转换成字符串,如果我们确定是小端形式的整形数,我们也可以自己来写转换方法。

#include <netinet/in.h>
#include <iostream>using namespace std;/**
小端 ip
*/
void ip_int_to_string(uint32_t ip)
{char buf[INET_ADDRSTRLEN]; // INET_ADDRSTRLEN = 16char n_buf[5];for (size_t i = 0; i < 4; ++i){char ch = (i == 3 ? '\0' : '.');int net = *((uint8_t*)(&ip) + i); // get each byte of ipsnprintf(n_buf, sizeof(n_buf), "%d%c", net, ch);strcat(buf, n_buf);}cout << buf << endl;
}/**
大端 ip
*/
void ip_int_to_string(uint32_t ip)
{char buf[INET_ADDRSTRLEN]; // INET_ADDRSTRLEN = 16char n_buf[5];for (size_t i = 3; i <= 3; --i){char ch = (i ? '.' : '\0');int net = *((uint8_t*)(&ip) + i); // get each byte of ipsnprintf(n_buf, sizeof(n_buf), "%d%c", net, ch);strcat(buf, n_buf);}cout << buf << endl;
}

 

# 后续

inet_pton 和 inet_ntop 是一组用于 ipv4 网络地址格式转换的方法。被包含在 #include <arpa/inet.h> 头文件中。

inet_pton 负责将 cost char * 的 IP 字符串转换为整数,inet_ntop 将 IP 整数值转换为字符串。

 

int inet_pton(int, const char *, void *);const char *inet_ntop(int, const void *, char *, socklen_t);int main()
{struct sockaddr_in addr;bzero(&addr, sizeof(addr)); // clear with 0inet_pton(AF_INET, "192.168.1.1", &(addr.sin_addr)); // "192.168.1.1" => addr.sin_addrcout << addr.sin_addr.s_addr << endl; // 16885952char ip[INET_ADDRSTRLEN];inet_ntop(AF_INET, &(addr.sin_addr), ip, INET_ADDRSTRLEN);cout << ip << endl; // 192.168.1.1
}

struct sockaddr_in 被包含在 #include <netinet/in.h> 头文件中,结构体定义如下

/** Socket address, internet style.*/
struct sockaddr_in {__uint8_t       sin_len;sa_family_t     sin_family;in_port_t       sin_port;struct  in_addr sin_addr;char            sin_zero[8];
};/** Internet address (a structure for historical reasons)*/
struct in_addr {in_addr_t s_addr;
};typedef __uint32_t      in_addr_t;      /* base type for internet address */

前面提到的 IP 整数值存放在 sin_addr 里,而它是 in_addr 结构体,包含一个成员 in_addr_t s_addr,而 in_addr_t 就是一个 uint32_t 无符号 int 类型。

inet_ntop(AF_INET, &(addr.sin_addr), ip, INET_ADDRSTRLEN);
// 也可以写成
inet_ntop(AF_INET, &(addr.sin_addr.s_addr), ip, INET_ADDRSTRLEN);
// 第二个参数可以传入一个整数指针

 

  相关解决方案