Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中比较套接字地址?_C_Sockets - Fatal编程技术网

如何在C中比较套接字地址?

如何在C中比较套接字地址?,c,sockets,C,Sockets,我的意思是,当我检查两个struct sockaddr是否具有相同的ip地址和端口号时,应该比较struct sockaddr的哪些字段?那么中的sockaddr\u呢 我可以将sockaddr\u放入sockaddr中,并将其与真实的sockaddr进行比较吗 首先需要检查该系列(IPv4、IPv6或其他)。然后可以将每个sockaddr强制转换为适当的“派生”类型,如中的sockaddr\u。看看苹果是如何做到这一点的:首先,当你处理值时,你需要使用struct sockaddr\u sto

我的意思是,当我检查两个
struct sockaddr
是否具有相同的ip地址和端口号时,应该比较
struct sockaddr
的哪些字段?那么中的
sockaddr\u呢


我可以将
sockaddr\u放入
sockaddr
中,并将其与真实的
sockaddr
进行比较吗

首先需要检查该系列(IPv4、IPv6或其他)。然后可以将每个sockaddr强制转换为适当的“派生”类型,如中的sockaddr\u。看看苹果是如何做到这一点的:

首先,当你处理值时,你需要使用
struct sockaddr\u storage
,因为
struct sockaddr
只对指针安全,否则你会遇到大小和对齐问题

其次,
struct sockaddr
是在C中传递的“基类”。第一个成员是
sau family\t sau family(虽然,由于此
struct
早于结构成员位于单独的名称空间中,所以每个“子类”使用唯一的前缀(我至少遇到过40个子类))

第三,虽然您可能认为每个
struct
定义都是可靠的,但事实证明,类的大小因内核/库版本而异。因此,您必须始终传递
sizeof()
实际的
struct sockaddr\u FOO
,以避免垃圾。例如,
struct sockaddr\u in6
的旧版本没有
sin6\u scope\u id
成员

您可能应该将其包装在
struct
中,以确保其完整性(并提供各种帮助函数):

然后,您的比较代码如下所示:

// 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;
}
//如果(左<右)返回<0
//如果(左>右),则返回>0
//如果(左==右),则返回0
//请注意,一般来说,“少”和“大”并不特别重要
//有意义,但这确实提供了严格的弱排序,因为
//你可能需要一个。
int socket_cmp(结构SocketAddress*左,结构SocketAddress*右)
{
socklen\u t min\u addr\u len=左->addr\u len<右->addr\u len?左->addr\u len:右->addr\u len;
//如果头部匹配,则长度越长。
int default_rv=right->addr_len-left->addr_len;
int rv=memcmp(左、右、最小地址);
返回rv?rv:默认的_rv;
}
但是等等!如果你小心的话,上面的代码就足够了,但是小心仍然需要很多细节。例如:

  • 是否所有套接字地址都将在程序的一次运行中生成,或者其中一些将从外部介质读取?对于后一种情况,您需要规范化类似于
    sin6\u scope\u id
    的情况

  • 您是否必须在同一个程序中同时处理IPv4和IPv4-on-IPv6地址(映射如
    ffff::1.2.3.4
    )?最简单的方法是在程序中专门处理IPv6,因为相关函数也接受IPv4地址。为了获得最佳的可移植性,请确保禁用(使用
    setsockopt
    )IPV6_V6ONLY
标志。或者,您可以启用该标志以帮助确保IPv6地址从不包含IPv4地址。(请注意,
localhost
的查找是不同的,但这是所有域查找的一个常见问题,可能会返回多个结果)

  • 您需要确保所有结构填充都为零


  • 你知道Mac/iOS上是否已经包含了
    sock\u addr.h
    ?@johk95正如你在url中看到的,sock\u addr.h和sock\u addr.c的源代码实际上来自postfix项目^^因为这实际上不是比较地址的正确方法,所以被否决。特别是,它不处理非IP地址,也不处理IPv6映射。这不是答案,因为代码没有给出
    SOCK\u ADDR\u IN\u ADDR
    SOCK\u ADDR\u IN 6\u ADDR
    的定义。但是,该代码可能会直接比较IPv4的
    s_addr
    ,并比较IPv6的整个平等结构。该代码不起作用,我认为解释中也缺少一些单词…@GregKennedy拼写错误现在应该得到纠正。当我写这篇文章时,我只是证明了它是正确的,而不是测试它。
    // 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;
    }