2011-03-20 21 views
1

我希望能够遍历getaddrinfo()函数的结果列表,并使用该列表的每个元素调用connect(),直到connect()成功。不幸的是,即使我指定AI_ALL | AI_V4MAPPED标志和AF_INET6系列,结果也是混合的。列表的第一部分包含结构,第二部分sockaddr_in结构,所以我不能将它们与AF_INET6套接字一起使用。有没有办法通过单个循环和IPv6套接字来处理getaddrinfo()输出?

我知道我可以创建两个套接字。我想知道是否有可能只用AF_INET6插座。

这里的操作系统:

> uname -a 
> Linux debian 2.6.32-5-amd64 #1 SMP Wed Jan 12 03:40:32 UTC 2011 x86_64 GNU/Linux 
+0

为什么你不能跳过v4地址? – Erik 2011-03-20 17:41:12

+0

@Erik:也许是因为有些主机不支持ipv6 ... – 2011-03-20 17:42:39

+0

@Adrien:我明白OP只需要ip6 ...也许不是。 – Erik 2011-03-20 17:44:39

回答

1

您不必担心,如果它是你正在创建一个AF_INET或AF_INET6插座。 只需将getaddrinfo()调用中的数据传递给socket()调用即可。

例如

/* returns -1 on error, or a connected socket descriptor*/ 
int opensock(const char *hostname, const char *service) 
{ 
    struct addrinfo hint, *host, *res = NULL; 
    int tcp_sd = -1, error; 

    memset(&hint, '\0', sizeof(hint)); 
    hint.ai_socktype = SOCK_STREAM; 
    hint.ai_family = PF_UNSPEC; 
    error = getaddrinfo(hostname, service, &hint, &res); 
    if(error){ 
     syslog(LOG_DEBUG,"getaddrinfo failed. Cant find host %s: %m",hostname); 
     return tcp_sd; 
    } 
    for (host = res; host; host = host->ai_next) { 
     tcp_sd = socket(host->ai_family, host->ai_socktype, host->ai_protocol); 
     if (tcp_sd < 0) { 
      continue; 
     } 

     if (connect(tcp_sd, host->ai_addr, host->ai_addrlen) < 0) { 
      close(tcp_sd); 
      tcp_sd = -1; 
      continue; 
     } 

     break;  /* okay we got one */ 
    } 

    freeaddrinfo(res); 

    return tcp_sd; 
} 
+0

谢谢,我想我想知道的是规范的做法。你是否碰巧知道在悲观的情况下多次调用socket()可能会导致性能下降,因为它需要内核完成一些工作? – kubi 2011-03-20 20:04:54

+0

这会损害性能。您可以记住套接字系列是否与前一个循环迭代中的相同,并避免在此情况下关闭并重新打开它。 – 2011-03-20 22:16:08

相关问题