c++ 双协议栈IPv6 in6addr_loopback与in6addr_any

yrdbyhpb  于 2022-12-01  发布在  其他
关注(0)|答案(1)|浏览(371)

我在Linux主机上设置了双堆栈,并尝试连接到可以侦听in6addr_loopbackin6addr_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地址一起工作?谢谢。

3phpmpom

3phpmpom1#

要在双栈侦听套接字上同时接受IPv4和IPv6客户端,应在对套接字执行bind()之前通过setsockopt()显式禁用IPV6_V6ONLY选项。
但是,更重要的是,绑定到in6addr_any::0)的双栈套接字将绑定到所有本地IPv4IPv6接口,而绑定到in6addr_loopback::1)的双栈套接字将只能绑定到IPv6环回接口,而不能绑定到IPv4环回接口(即::1!= 127.0.0.1)。

相关问题