什么时候getaddrinfo返回列表中的多个sockaddr结构?

时间:2019-05-01 21:41:37

标签: c windows sockets

我正在使用发现的一些代码,并且试图理解其中的 for循环 逻辑。

似乎没有使用for循环,并且总是会中断。所以我不明白getaddrinfo()返回的是哪种信息,这会导致该信息再次循环并检查某些内容?

问题:基本上,这是什么for循环试图完成?在我看来,这只是检查列表是否为NULL,因为永远不会发生循环。

tcp_ctx* tcp_new_ctx(INT family, CHAR *host, CHAR *port) {
    struct addrinfo *list = NULL;
    struct addrinfo *e = NULL;
    struct addrinfo hints;
    tcp_ctx         *c = NULL;
    WSADATA         wsa;
    INT             on = 1;

    WSAStartup(MAKEWORD(2, 0), &wsa);

    ZeroMemory(&hints, sizeof(hints));

    hints.ai_family = family;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // try to resolve network address for host
    //list contains linked list of addrinfo structs containing information on the host
    if (getaddrinfo(host, port, &hints, &list) != 0) {
        return NULL;
    }
    c = tcp_alloc(sizeof(tcp_ctx));

    // Traverse linked list from getaddr info
    for (e = list; e != NULL; e = e->ai_next) {
        if (family == AF_INET) {
            memcpy(&c->v4, e->ai_addr, e->ai_addrlen);
            c->ai_addr = (SOCKADDR*)&c->v4;
        } else if (family == AF_INET6) {
            memcpy(&c->v6, e->ai_addr, e->ai_addrlen);
            c->ai_addr = (SOCKADDR*)&c->v6;
        } else {
            return NULL;
        }
        c->ai_addrlen = e->ai_addrlen;
        // create socket and event for signalling
        c->s = socket(family, SOCK_STREAM, IPPROTO_TCP);
        if (c->s != SOCKET_ERROR) {
            // ensure we can reuse same port later
            setsockopt(c->s, SOL_SOCKET, SO_REUSEADDR, (CHAR*)&on, sizeof(on));
        }
        break;
    }
    freeaddrinfo(list);
    return c;
}

1 个答案:

答案 0 :(得分:3)

列表中将包含什么?

以下引文来自man page of getaddrinfo of glibc,但AFAIK同样适用于Windows版本:

  

链接列表可能有多个原因有多个原因          addrinfo结构,包括:网络主机是多宿主的,可以通过多种协议访问(例如,AF_INET和AF_INET6);要么          可以从多种套接字类型获得相同的服务(一种          例如,SOCK_STREAM地址和另一个SOCK_DGRAM地址。

因此,基本上,主机可以有多种联系方式,getaddrinfo列出了所有(已知)方式。请注意,同一手册页还指出:

  

通常,应用程序应尝试按顺序使用地址          在其中返回。在getaddrinfo()中使用的排序功能在RFC 3484中定义;

当然,在这里我们也不知道这是否也适用于Windows实现,但是如果在RFC中指定了,则可能是这种情况。

这是什么for循环试图完成?

目前,您可以删除循环。我认为,也许有理由保留(=修复)它:考虑以下情况:第一个返回的条目的family既没有AF_INET也没有AF_INET6。这样,您问题中的代码就会失败(return NULL;),但是列表中的后面可能会有该家族的条目。