IPV6 socket connect()返回EADDRNOTAVAIL

时间:2016-06-13 06:04:06

标签: c++ sockets ipv6

我试图通过对Appstore的IPv6支持,并遇到一些问题。

我关注了Apple的公会Supporting IPv6 DNS64/NAT64 Networks,我的代码是:

const char sAddr[] = "123.123.123.123"; //my IPv4 gamesvr, using boost asio
const char sPort[] = "9899";
const char *cause = NULL;
int sock_;
struct addrinfo hints, *res, *res0;

memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_DEFAULT;

int error = getaddrinfo(sAddr, sPort, &hints, &res0);
if (error) {
    return false;
}
sock_ = -1;
for (res = res0; res; res = res->ai_next) {
    sock_ = socket(res->ai_family, res->ai_socktype,res->ai_protocol);
    if (sock_ < 0) {
        cause = "socket";
        continue;
    }
    if (::connect(sock_, res->ai_addr, res->ai_addrlen) < 0) {
        error = errno; // error = 49, EADDRNOTAVAIL
        break;
    }
    break;  /* okay we got one */
}
if (sock_ < 0) {
    freeaddrinfo(res0);
    return false;
}
freeaddrinfo(res0);
return true;

在IPv4 WIFI下,我的游戏运行良好。

当切换到IPv6-ONLY WIFI(由mac运行)时,使用CURL的函数运行良好,我可以获取Web内容,但socket connect()失败,错误号为49(EADDRNOTAVAIL),res-&gt; ai_family = 30(AF_INET6 )

任何人都请帮助我,非常感谢!

2 个答案:

答案 0 :(得分:1)

尝试将break后的error = errno;更改为continue。如果connect失败,您应该尝试下一个地址。

解析器可能仍会为您提供原始IPv4结果 NAT64的综合IPv6结果。如果您获得的错误来自于在仅IPv6网络上创建IPv4套接字,我不会感到惊讶。

答案 1 :(得分:0)

我解决了它,虽然我不知道为什么......

令人惊讶的是,当我尝试使用域名而不是数字IP地址时,连接就可以了!

const char sAddr [] =“123.123.123.123”; - &GT; const char sAddr [] =“gs1.mydomain.com”;

我的游戏在IPv6-ONLY WIFI下运行正常!

现在我很困惑为什么Apple将这些放入Supporting IPv6 DNS64/NAT64 Networks

uint8_t ipv4[4] = {192, 0, 2, 1};
struct addrinfo hints, *res, *res0;
int error, s;
const char *cause = NULL;

char ipv4_str_buf[INET_ADDRSTRLEN] = { 0 };
const char *ipv4_str = inet_ntop(AF_INET, &ipv4, ipv4_str_buf, sizeof(ipv4_str_buf));

memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_DEFAULT;
error = getaddrinfo(ipv4_str, "http", &hints, &res0);
  

清单10-1显示了如何使用getaddrinfo解析IPv4文本。假设您将IPv4地址存储在内存中作为四个字节(例如{192,0,2,1}),此示例代码将其转换为字符串(例如“192.0.2.1”),使用getaddrinfo来合成IPv6地址(例如包含IPv6地址“64:ff9b :: 192.0.2.1”的struct sockaddr_in6)并尝试连接到该IPv6地址。

-_- ||