C++ connect()返回";无效参数";使用ipv6地址
我有一个简单的客户机-服务器应用程序对。代码非常简单,我只使用了新的建议方法,如getaddinfo等,并且对于ipv4来说一切都很好。即使对于ipv6环回(::1),它也可以工作。当涉及到其他ipv6地址时,就会出现问题。。。我在一个网络中有两台机器,当我传递它们的ipv4地址时,一切正常,但当我给我的客户端ipv6地址时,我在连接函数上得到一个错误:无效参数。 嘿,我不是已经知道了吗?我愿意!当我尝试ping6此ipv6地址时,我得到了相同的错误: connect:参数无效 但是有一种方法可以克服这个障碍——我们应该选择一个带有a-I开关的接口,从那时起它就可以顺利运行。但如何在我的客户端应用程序中实现同样的效果呢?我该怎么办?我的客户端代码如下所示:C++ connect()返回";无效参数";使用ipv6地址,c++,c,arguments,connect,C++,C,Arguments,Connect,我有一个简单的客户机-服务器应用程序对。代码非常简单,我只使用了新的建议方法,如getaddinfo等,并且对于ipv4来说一切都很好。即使对于ipv6环回(::1),它也可以工作。当涉及到其他ipv6地址时,就会出现问题。。。我在一个网络中有两台机器,当我传递它们的ipv4地址时,一切正常,但当我给我的客户端ipv6地址时,我在连接函数上得到一个错误:无效参数。 嘿,我不是已经知道了吗?我愿意!当我尝试ping6此ipv6地址时,我得到了相同的错误: connect:参数无效 但是有一种方法可
struct addrinfo hints;
struct addrinfo *server;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int status;
if((status = getaddrinfo(argv[1], argv[2], &hints, &server) != 0))
{
perror("getaddrinfo error");
return 1;
}
int sock_fd;
struct addrinfo *ptr;
for(ptr=server;ptr!=NULL;ptr=ptr->ai_next)
{
if( (sock_fd = socket(ptr->ai_family,ptr->ai_socktype,ptr->ai_protocol)) == -1)
{
perror("socket error");
continue;
}
if( connect(sock_fd, ptr->ai_addr,ptr->ai_addrlen) == -1 )
{
perror("connect error");
continue;
}
break;
}
我的建议是,在接口/网络连接中打开IP6协议,此外,如果仍然存在错误,请扔掉ip4协议 在我的Linux机器上,当我有一个ip4接口处于活动状态,并且我的应用程序尝试使用ip4接口和ip6设置时,这种情况也发生了。这同样适用于windows
如果不清楚,请询问。以
ff…
开头的地址是多播地址。将流连接到多播地址不起作用
以
fe80…
开头的地址是链接本地地址,具有与其关联的接口标识符。尝试查看从getaddrinfo
返回的sockaddr
,是否填写了scope
字段?您需要指定IPv6 ping的接口(即-i eth0):
使用IPv6 ping的链路本地地址需要定义它必须发送/接收数据包的设备-每个设备都有一个链路本地地址
在没有此选项的情况下尝试,将导致如下错误消息:
--> # ping6 fe80::208:54ff:fe34:22ae
connect: Invalid argument
在这种情况下,您必须另外指定接口,如下所示:
--> # ping6 -I eth0 fe80::208:54ff:fe34:22ae
PING fe80::208:54ff:fe34:22ae(fe80::208:54ff:fe34:22ae) from fe80::208:54ff:fe34:22ae eth0: 56 data bytes
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=0 ttl=64 time=0.027 ms
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=2 ttl=64 time=0.036 ms
在客户端应用程序中,您必须遵循一种类似的方法。ping拒绝的这个有问题的地址是什么?我正在ping网络中的另一台计算机,但它对所有ipv6地址都有效-检查此项:@flyjohny也许您应该检查您的路由,看看默认路由是否为ip6路由命令:“route-A inet6”我知道我很懒,但你能告诉我如何在接口中打开ip6协议吗?我使用的是Linux设备。首先检查本指南,然后在您的特定接口上尝试此操作:ping6-I eth0“在此处填充ip6addr”可能是您的环回接口已激活ip6支持,因此本地ping工作没有问题,你能告诉我们你的Linux发行版和内核版本吗?这个字段应该包含接口号。您是否使用
%eth0
或%1
(1是接口号,您可以使用ip
工具)符号指定范围?\n否。当我这样做的时候,这个范围字段被填充了一些值,它似乎可以工作(虽然我需要配置我的特定FW,但我不再得到无效参数)。但我似乎错过了一些东西,在我阅读的所有与ipv6相关的材料中,我没有遇到过这一点——我是否需要在使用链接本地地址时指定接口?是的,您需要。链接本地地址恰恰意味着地址的唯一性只在这个特定的链接上得到保证,因此除非您告诉系统,否则系统无法找到将数据发送到哪个接口。另一种方法是分配具有全局作用域的地址并使用路由表。@SimonRichter-如果我使用的是本地链接地址,是否意味着作用域id字段将始终为0,我们需要显式指定它?系统是否可以使用/etc/hosts中的任何配置或任何其他配置自动选择此选项?(注意:我的网络中没有DNS)@kaps,没有,没有办法让系统自动选择接口。将ppp0
、ppp1
和ppp2
都配置为使用本地地址fe80::1
和对等地址fe80::2
,这是完全合法的,因此操作系统无法决定将哪个接口用于目标地址fe80::2
。因此,程序需要填写范围\u id
。当用户配置地址时,当用户使用%
符号时,getaddrinfo
将填写地址,当您使用多播进行查找时,您可以使用查找数据包来源的作用域ID。
--> # ping6 -I eth0 fe80::208:54ff:fe34:22ae
PING fe80::208:54ff:fe34:22ae(fe80::208:54ff:fe34:22ae) from fe80::208:54ff:fe34:22ae eth0: 56 data bytes
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=0 ttl=64 time=0.027 ms
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=2 ttl=64 time=0.036 ms