-->

连接IPv4客户端向IPv6服务器:连接被拒绝(Connecting IPv4 client to

2019-09-02 11:36发布

我与IPv6的试验插座,默认情况下在Windows Vista及更高版本,显然在Unix提供特别是“双栈”的能力。 我发现,当我在我的服务器绑定到特定的IP地址,或以我的本地机器的主机名解析,我不能接受一个I​​Pv4客户端的连接。 当我然而绑定到INADDR_ANY,我可以。

请考虑我的服务器下面的代码。 你可以看到,我按照创建一个IPv6套接字,那么IPV6_V6ONLY标志设置为零的微软的建议是:

addrinfo* result, *pCurrent, hints;

memset(&hints, 0, sizeof hints);    // Must do this!
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;     // We intend to use the addrinfo in a call to connect().  (I know it is ignored if we specify a server to connect to...)

int nRet = getaddrinfo("powerhouse", "82", &hints, &result);

SOCKET sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);

int no = 0;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) != 0)
    return -1;

if (bind(sock, result->ai_addr, result->ai_addrlen) ==  SOCKET_ERROR)
    return -1;

if (listen(sock, SOMAXCONN) == SOCKET_ERROR)
    return -1;

SOCKET sockClient = accept(sock, NULL, NULL);

这里是我的客户端代码。 你可以看到我创建IPv4套接字,并尝试连接到我的服务器:

addrinfo* result, *pCurrent, hints;

memset(&hints, 0, sizeof hints);    // Must do this!
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

if (getaddrinfo("powerhouse", "82", &hints, &result) != 0)
    return -1;

SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
int nRet = connect(sock, result->ai_addr, result->ai_addrlen);

从我的连接调用的结果总是10061:连接被拒绝。

如果我改变我的服务器代码绑定到::(或传递一个NULL主机的getaddrinfo()(同样的事情)),并改变我的客户端代码可以指定在的getaddrinfo()调用一个NULL主机,则V4客户端可以连接精细。

任何人都可以解释为什么吗? 我没有看到任何东西,我们必须指定一个NULL主机(因此使用INADDR_ANY)如果我们想双插槽的行为。 这不可能是一个要求,因为我有一个多宿主主机,我想接受的IPv4上只有部分可用IP的?

编辑15/05/2013:

这是已经得到了我的困惑,为什么我的代码失败的相关文件:

从双栈套接字IPv6的Winsock应用程序

“Windows Vista和更高版本提供了创造,它可以处理IPv6和IPv4流量的一个IPv6套接字的能力。例如,对IPv6的TCP监听套接字的建立,投入双栈模式,并绑定到端口5001。这双堆栈插座可以接受来自IPv6的TCP客户端连接到端口5001和从IPv4 TCP客户端的连接连接到端口5001。”

“默认情况下,在Windows Vista中创建和更高版本IPv6套接字工作在IPv6协议。为了使IPv6套接字成双栈插座,setsockopt函数必须与IPV6_V6ONLY套接字选项调用这个值设置为零点前的套接字绑定到一个IP地址。 当IPV6_V6ONLY套接字选项设置为零,为AF_INET6地址族创建的套接字可用于发送和接收数据包,并从IPv6地址或IPv4映射地址。(重点煤矿)”

Answer 1:

IPv4和IPv6是两个独立的协议。 一个协议的分组可以不使用其他协议来处理。 这就是为什么双协议栈的概念存在:您的系统同时运行IPv4和IPv6协议栈,同时具有IPv4和IPv6地址,等等。

操作系统都有一个技巧,你可以拥有所有的IPv4和IPv6地址监听IPv6套接字。 您仍然需要在主机上两个地址的家庭,当你绑定到通配符地址它仅适用。 一旦你套接字绑定到一个固定的地址,不工作了,它会只对你已经绑定到地址工作。

所以,如果你想监听所有可用的地址,然后设置IPV6_V6ONLY为0,并侦听通配符地址的工作。 IPv4的客户端将被示出为使用IPv6地址开始::ffff:用含有IPv4地址的最后32位。

当你要绑定到特定地址,您将需要绑定到每个你要听上的地址的插座。 然后,你需要使用IE浏览器select(...)来监控这些插槽和那些因为有人连接到它们将成为活动作出回应。



Answer 2:

此链接http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch12lev1sec2.html给出了关于IPv4和IPv6连接的详细信息,

大多数的双栈主机应该在处理监听套接字使用以下规则:

  • 听音IPv4套接字可以接受来自仅支持IPv4的客户端的连接。
  • 如果服务器有没有设置已绑定的通配符地址,IPV6_V6ONLY套接字选项(7.8节),一个监听IPv6套接字,该套接字可以接受来自任何客户端的IPv4或IPv6客户端的连接。 对于从IPv4客户端的连接,服务器的本地地址的连接将被相应的IPv4映射的IPv6地址。
  • 如果服务器有一个绑定的IPv6比IPv4映射的IPv6地址的地址等,或已绑定的通配符地址,但已成立了IPv6_V6ONLY套接字选项(7.8节)监听IPv6套接字,该套接字可以接受来自IPv6客户端的传入连接只要。


文章来源: Connecting IPv4 client to IPv6 server: connection refused