我正在使用发现的一些代码,并且试图理解其中的 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;
}
答案 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;
),但是列表中的后面可能会有该家族的条目。