将IP地址从sockaddr转换为in_addr

时间:2015-01-06 14:32:49

标签: 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的最佳方法是什么?

1 个答案:

答案 0 :(得分:5)

sockaddr是一个通用结构,由不同类型的套接字共享。对于TCP / IP套接字,此结构变为sockaddr_in。对于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_in6 更大而不是sockaddr,因此从sockaddr投射到sockaddr_in6时,请确保该地址通过检查地址系列foo.sa_family == AF_INET6确实是一个IPv6地址。