我的意思是,在检查两个struct sockaddr
是否具有相同的IP地址和端口号时,我应该比较哪些struct sockaddr
的字段?那么sockaddr_in
呢?
我可以将sockaddr_in
强制转换为sockaddr
,并将其与真实的sockaddr
进行比较吗?
首先需要检查协议家族 (IPv4、IPv6 或其他)。然后,您可以将每个 sockaddr 强制转换为适当的“派生”类型,例如 sockaddr_in。 在此处查看 Apple 的操作方式:http://www.opensource.apple.com/source/postfix/postfix-197/postfix/src/util/sock_addr.c
struct sockaddr_storage
,因为struct sockaddr
仅对指针安全,否则将遇到大小和对齐问题。struct sockaddr
在C中用作“基类”。第一个成员是sa_family_t sa_family;
(尽管由于此struct
早于结构成员位于单独的命名空间中,因此每个“子类”使用唯一的前缀(我至少遇到了40个子类))。struct
定义都是可靠的,但事实证明类的大小因内核/库版本而异。因此,您始终必须传递实际struct sockaddr_FOO
的sizeof()
以避免垃圾。例如,旧版本的struct sockaddr_in6
没有sin6_scope_id
成员。struct
中以保持清晰(并提供各种辅助函数)。struct SocketAddress
{
struct sockaddr_storage addr;
socklen_t addr_len;
};
// returns < 0 if (left < right)
// returns > 0 if (left > right)
// returns 0 if (left == right)
// Note that in general, "less" and "greater" are not particularly
// meaningful, but this does provide a strict weak ordering since
// you probably need one.
int socket_cmp(struct SocketAddress *left, struct SocketAddress *right)
{
socklen_t min_addr_len = left->addr_len < right->addr_len ? left->addr_len : right->addr_len;
// If head matches, longer is greater.
int default_rv = right->addr_len - left->addr_len;
int rv = memcmp(left, right, min_addr_len);
return rv ? rv : default_rv;
}
等等!虽然上面的代码足够小心,但小心仍然需要注意很多细节。例如:
所有套接字地址是否都将在程序的单个运行中生成,还是有些套接字地址将从某些外部介质中读取?对于后一种情况,您将希望规范化像sin6_scope_id
这样的情况。
您是否需要在同一个程序中处理IPv4和IPv4-on-IPv6地址(映射为ffff::1.2.3.4
)?最简单的方法是在程序中专门处理IPv6,因为相关函数也接受IPv4地址。为了获得最佳的可移植性,请确保使用setsockopt
禁用IPV6_V6ONLY
标志。或者,您可以启用该标志,以确保IPv6地址永远不包含IPv4地址。(请注意,查找localhost
的方式不同 - 但这是所有域名查找的一般问题,可能会返回多个结果)。
您需要确保所有结构填充都被清零。
sock_addr.h
吗? - johk95SOCK_ADDR_IN_ADDR
或SOCK_ADDR_IN6_ADDR
的定义。然而,该代码可能直接比较s_addr
来判断IPv4,对于IPv6则比较整个结构体是否相等。 - EML