繁体   English   中英

无法将套接字绑定到IPv4和IPv6中的端口

[英]Cannot Bind Socket to Port in Both IPv4 and IPv6

我是套接字编程的新手,当遇到障碍时,我正在研究一些临时代码来更好地理解它。 任何关于我做错事情的指导将不胜感激!

我试图编写一个简单的程序,该程序绑定并侦听用户指定的端口,并向任何连接发送“ Hello”消息。 对于踢,我想我只会在同一端口上侦听所有IPv4和IPv6地址。 这是一个代码片段:

memset(&hints, 0, sizeof hints);
hints.ai_family   = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags    = AI_PASSIVE;

if ( getaddrinfo(NULL, argv[1], &hints, &res) != 0 ) { 
    printf("getaddrinfo failed!\n");
    return 1;
}

for ( addrinfo* p = res; p != NULL; p = p->ai_next ) { 
    inet_ntop(p->ai_family, get_addr_ptr(p->ai_addr), ipstr, sizeof ipstr);
    printf("Found IP: %s\n",ipstr);

    printf("\tGetting socket...\t");
    sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
    if ( sockfd == -1 ) { 
        perror("\t\tError");
        continue;
    }
    printf("OK\n");

    printf("\tBind Socket to Port...\t");
    if ( bind(sockfd, p->ai_addr, p->ai_addrlen) == -1 ) { 
        perror("\t\tError");
        close(sockfd);
        continue;
    }
    printf("OK\n");

    printf("\tListen on socket...\t");
    if ( listen(sockfd, BACKLOG) == -1 ){
        perror("\t\tError");
        continue;
    }
    printf("OK\n");
}

freeaddrinfo(res);
while (1) {/* accept connections */}

运行代码时,得到以下输出:

$ ./simpleServer 8080
Found IP: 0.0.0.0
    Getting socket...       OK
    Bind Socket to Port...  OK
    Listen on socket...     OK
Found IP: ::
    Getting socket...       OK
    Bind Socket to Port...
        Error: Address already in use

但是,如果我在程序运行时查看netstat ,则看不到与::绑定的任何冲突端口,或与此相关的任何其他IPv6地址。

我对此进行了更多研究,发现我可以仅使用IPv4或仅使用IPv6绑定到端口,但不能同时使用这两种端口,我不理解。 我创建了两个套接字,其中包含以下ai_addr:

  • 家族: AF_INET地址信息: 0.0.0.0:8008 : 0.0.0.0:8008
  • 家庭: AF_INET6地址信息:::8080

我觉得我可能缺少一些基本知识,但我看不到。

谢谢!

您面临的问题可能是您正在使用双栈模式。 至少在Linux上(其他人经常禁用它,例如FreeBSD),将::指定为地址,并绑定到netstatss表示的* 这意味着它接受IPv6和IPv4地址。 尽管IPv4 ::ffff:<your normal ipv4 address>映射到::ffff:<your normal ipv4 address> 所以我想您也遇到了同样的问题。

如果af_family == AF_INET6 ,则可以使用IPV6_V6ONLY套接字选项来不允许这种行为。

IPV6_V6ONLY(从Linux 2.4.21和2.6开始)如果此标志设置为true(非零),则套接字将被限制为仅发送和接收IPv6数据包。 在这种情况下,IPv4和IPv6应用程序可以同时绑定到单个端口。 如果此标志设置为false(零),则套接字可用于与IPv6地址或映射了IPv4的IPv6地址之间收发数据包。

参数是一个指向整数的布尔值的指针。

此标志的默认值由文件/ proc / sys / net / ipv6 / bindv6only的内容定义。 该文件的默认值为0(假)。

取自男子7 ipv6

请注意,您正在覆盖以前创建/绑定/监听的套接字。 还可以使用gai_strerrorgetaddrinfo的返回值中获取有意义的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM