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 (将#修改为@)