【问题标题】:IPV6 socket connect() returns EADDRNOTAVAILIPV6 套接字 connect() 返回 EADDRNOTAVAIL
【发布时间】:2016-06-13 06:04:05
【问题描述】:

我正在尝试通过对 Appstore 的 IPv6 支持,但遇到了一些问题。

我关注了 Apple's Guild 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 的功能运行良好,我可以获取网页内容,但 socket connect() 失败,错误码 49(EADDRNOTAVAIL),res->ai_family = 30 (AF_INET6)

请大家帮帮我,非常感谢!

【问题讨论】:

  • 为什么要将 IPv4 地址传递给getaddrinfo?让我想知道为什么当你关闭 IPv4 时这会返回任何东西,可能它只是转换后的 IPv4 地址,然后在没有 IPv4 网络的情况下不起作用。我猜,在那里使用 DNS 名称会更有意义。
  • Apple 在“使用系统 API 合成 IPv6 地址”中说,“如果您的应用需要连接到没有 DNS 主机名的仅 IPv4 服务器,请使用 getaddrinfo 来解析 IPv4 地址文字”,我的代码只是按照示例...
  • 所以你的网络只有 IPv6,而你的服务器只有 IPv4?
  • 你在这里疯狂地泄漏套接字。

标签: c++ sockets ipv6


【解决方案1】:

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

解析器可能仍会为您提供原始 IPv4 结果 NAT64 的合成 IPv6 结果。如果您遇到的错误是尝试在纯 IPv6 网络上创建 IPv4 套接字,我不会感到惊讶。

【讨论】:

  • 请说明您从getaddrinfo返回的具体内容
【解决方案2】:

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

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

const char sAddr[] = "123.123.123.123"; --> 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 地址。

-_-||

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 2012-08-28
    • 2012-07-27
    • 1970-01-01
    相关资源
    最近更新 更多