问题描述
我是 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 (将#修改为@)