微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

IPV4 客户端到 IPV6 服务器连接问题

如何解决IPV4 客户端到 IPV6 服务器连接问题

我是 IPV6 的新手,我需要将我的 IPV4 代码迁移到双栈。我有两个应用程序,一个支持 IPV6(双栈)并在服务器端使用,另一个基本上是仅 IPV4 的客户端。

请注意,在同一主机上,有一台服务器和多个客户端。由于设备支持双栈,一些封闭的应用程序只能使用 IPV4 来与我的服务器通信。因此,我正在尝试使用环回 IP。

当我在服务器端为“::1”地址创建套接字时,客户端无法使用“127.0.0.1”地址连接它。但是,当我在“::”地址上运行服务器时,客户端可以连接,而在服务器端,我将客户端 IP 视为 IPV4 映射地址 (::ffff.127.0.0.1)。但问题是,出于安全考虑,我需要在“::1”地址上运行服务器

这是我在服务器端截取代码

   struct addrinfo hints,*result,*rp;
   int rc = 0;
   int sck = -1;

   memset(&hints,sizeof(struct addrinfo));
   hints.ai_family = AF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_protocol = 0;

   rc = getaddrinfo("::1","9999",&hints,&result);
   if (rc != 0) {
       goto fail;
   }

   if (!result) {
       goto fail;
   }

   for (rp = result; rp != NULL; rp = rp->ai_next) {
       sck = socket(rp->ai_family,rp->ai_socktype,0);
       if (sck == -1) {
           continue;
       }
       int yes = 1;
       if (setsockopt(sck,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) < 0) {
           goto fail;
       }
       int v6OnlyEnabled = 0;
       if (setsockopt(sck,IPPROTO_IPV6,IPV6_V6ONLY,&v6OnlyEnabled,sizeof(v6OnlyEnabled)) != 0) {
           goto fail;
       }

       if (bind(sck,rp->ai_addr,rp->ai_addrlen) == 0) {
           break; //Success
       }

       //Fail
       close(sck);
       sck = -1;
   }

   freeaddrinfo(result);

   if (sck == -1) {
       goto fail;
   }

   rc = listen(sck,10);
   if (rc < 0) {
       //error
       goto fail;
   }

fail:

   close(sck);
   sck = -1;

这里是客户端;

    struct addrinfo hints,*addr_list,*cur;
    int retry = 0;
    int sck = -1;
    int rc = 0;
    int val;
    long arg;
    struct pollfd pollfd;
    socklen_t len = 0;


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

    rc = getaddrinfo("127.0.0.1",&addr_list);

    if (rc != 0) {
        printf("fail: %d\n",__LINE__);
        goto fail;
    }

    for (cur = addr_list; (cur != NULL); cur = cur->ai_next) {
        sck = socket(cur->ai_family,cur->ai_socktype,0);
        if (sck < 0) {
            continue;
        }

        arg = fcntl(sck,F_GETFL,NULL);
        arg |= O_NONBLOCK;
        if (fcntl(sck,F_SETFL,arg) < 0) {
            printf("fail: %d\n",__LINE__);
            goto fail;
        }

        retry = 3;
        while (--retry) {
            //connecting
            rc = connect(sck,cur->ai_addr,cur->ai_addrlen);

            if (rc == 0) {
                printf("OK: %d\n",__LINE__);
                break;
            }

            pollfd.fd = sck;
            pollfd.events = POLLIN | POLLOUT;
            pollfd.revents = 0;
            rc = poll(&pollfd,1,100000);
            if (rc == 0) {
                //timeout
                printf("fail: %d\n",__LINE__);
                close(sck);
                sck = -1;
                break;
            }

            len = sizeof(val);
            rc = getsockopt(sck,SO_ERROR,(void *) (&val),&len);
            if (rc < 0) {
                //fail
                printf("fail: %d\n",__LINE__);
                close(sck);
                sck = -1;
                break;
            }

            if (val == EALREADY || val == EINPROGRESS) {
                //connecting
                printf("connecting: %d\n",__LINE__);
                break;
            }

            if (val == ECONNREFUSED) {
                (void)poll((void *)0,(unsigned long)0,(int)1000);
            }
        }
    }
    freeaddrinfo(addr_list);

    if (sck < 0)
        printf("fail %d\n",__LINE__);

fail:

   close(sck);
   sck = -1;

似乎禁用“IPV6_V6ONLY”选项不起作用。 另外,我已经比较了“proc/sys/net/ipv6/conf/lo”和“all”文件夹的内容。它们看起来一样(除了 use_tempaddr 和 mtu)

请帮我解决这个问题。

谢谢

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。