将 IP 地址从 sockaddr 转换为 in_addr
Convert IP address from sockaddr to in_addr
我需要将结构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
(主机到网络)转换 to/from 主机字节顺序。
更新
对于 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 地址
我需要将结构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
(主机到网络)转换 to/from 主机字节顺序。
更新
对于 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
.