我在Linux主机上设置了双堆栈,并尝试连接到可以侦听in6addr_loopback
或in6addr_any
的TCP/IPv6服务器,下面是一个非常简单的服务器示例:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
if (argc != 2)
exit(1);
struct sockaddr_in6 serv6;
memset(&serv6, 0, sizeof(struct sockaddr_in6));
int fd6 = socket(AF_INET6, SOCK_STREAM, 0);
int loopback = atoi(argv[1]);
if (loopback)
serv6.sin6_addr = in6addr_loopback;
else
serv6.sin6_addr= in6addr_any;
serv6.sin6_port = htons(3000);
serv6.sin6_family = AF_INET6;
int opt = 1;
setsockopt(fd6, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
if (bind(fd6, (struct sockaddr *)&serv6, sizeof(struct sockaddr_in6)) < 0) {
perror("bind");
exit(1);
}
listen(fd6, 5);
int cli = accept(fd6, NULL, NULL);
char buf[10] = {0};
int n = read(cli, buf, 9);
if (n > 0)
fprintf(stderr, "received %d bytes : %s from ipv6 stack\n", n, buf);
else
perror("read");
exit(0);
}
我在同一台主机上使用ncat
以以下方式连接到服务器:
服务器正在侦听in6addr_any
:
ncat 127.0.0.1 3000 // OK
ncat ::1 3000 // OK
ncat ::ffff:127.0.0.1 3000 // OK
服务器正在侦听in6addr_loopback
:
ncat 127.0.0.1 3000 // Ncat: Connection refused.
ncat ::1 3000 // OK
ncat ::ffff:127.0.0.1 3000 // Ncat: Connection refused.
为什么它只能与环回接口的IPv6地址一起工作?谢谢。
1条答案
按热度按时间3phpmpom1#
要在双栈侦听套接字上同时接受IPv4和IPv6客户端,应在对套接字执行
bind()
之前通过setsockopt()
显式禁用IPV6_V6ONLY
选项。但是,更重要的是,绑定到
in6addr_any
(::0
)的双栈套接字将绑定到所有本地IPv4和IPv6接口,而绑定到in6addr_loopback
(::1
)的双栈套接字将只能绑定到IPv6环回接口,而不能绑定到IPv4环回接口(即::1
!=127.0.0.1
)。