c++ - 将 IP 地址从 sockaddr 转换为 in_addr

标签 c++ sockets visual-c++

我需要将结构sockaddr 中的套接字地址转换为结构in_addr。我试图了解 IP 如何存储在这些结构中:

struct sockaddr
{
    u_short sa_family;      /* address family */
    char    sa_data[14];    /* up to 14 bytes of direct 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;
    }
    S_un;
};

我对 127.0.0.1 如何存储在 sa_data 的 14 个字符中感到困惑。 将 sockaddr 转换为 in_addr 的最佳方法是什么?

最佳答案

sockaddr 是一个通用结构体,由不同类型的套接字共享。对于 TCP/IP 套接字,此结构变为 sockaddr_in (IPv4) 或 sockaddr_in6 (IPv6)。对于 unix 套接字,它变为 sockaddr_un

理想情况下,您应该使用 sockaddr_in 而不是 sockaddr

但是给定 sockaddr,您可以这样做以从中提取 IP 地址:

sockaddr foo;
in_addr ip_address = ((sockaddr_in)foo).sin_addr;
or
in_addr_t ip_address = ((sockaddr_in)foo).sin_addr.s_addr;

如果查看 sockaddr_in,您会看到 sa_data 的前 2 个字节是端口号。接下来的 4 个字节是 IP 地址。

PS:请注意 IP 地址以网络字节顺序存储,因此您可能需要使用 ntohl(网络到主机)和 htonl(主机到网络)转换为/从主机字节顺序。

更新

对于 IPv6,情况类似:

sockaddr foo;
in_addr6 ip_address = ((sockaddr_in6)foo).sin6_addr;

要访问单个字节,请使用 ip_address[0] ... ip_address[15]

sockaddr_in6 结构中,sa_data 的前 2 个字节是端口号,接下来的 4 个字节是流信息,接下来的 16 个字节是 IPv6 地址。

但是请注意,sockaddr_in6sockaddr ,因此当从 sockaddr 转换为 sockaddr_in6,通过检查地址族 foo.sa_family == AF_INET6 确保该地址确实是 IPv6 地址。

关于c++ - 将 IP 地址从 sockaddr 转换为 in_addr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27800842/

相关文章:

c++ - 拆分用户在参数中输入的字符串

Java - 发送到 OutputStream 的两个字符串之间的差异

perl - 从Perl中的套接字读取特定数量的字节

c++ - Visual C++ 对 std::map 的实现

c++ - 使用索引将 BST 值存储到数组中

c# - 访问位图的字节数组

c++ - 删除数组指针

java - Play2 长期套接字连接和多线程

c++ - 等待 main() 返回?

c++ - 使用 C++ 在同一系统上运行的两个服务之间的通信