首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >移植IPv4应用到双栈IPv4/IPv6

移植IPv4应用到双栈IPv4/IPv6
EN

Stack Overflow用户
提问于 2012-12-19 17:59:30
回答 3查看 1.4K关注 0票数 2

实际上,我正在将IPv4服务器应用程序移植到Linux上的双栈IPv4/IPv6应用程序。

我已经用以下方法解决了基本函数:

代码语言:javascript
复制
serv_addr.sin6_family = AF_INET6;
serv_addr.sin6_addr = in6addr_any;
...
bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
...
listen(sock, 5);
...
newsock = accept(syn->sock, (struct sockaddr *) &cli_addr, &clilen);

我可以连接IPv4和IPv6并使用这些连接。但是当我想要获取IP地址时:

代码语言:javascript
复制
switch(data->sa_family) {
   case AF_INET:
   inet_ntop(AF_INET, &(((struct sockaddr_in*)data)->sin_addr), buffer, size);
   break;
   case AF_INET6:
   inet_ntop(AF_INET6, &(((struct sockaddr_in6*)data)->sin6_addr), buffer, size);
   break;

   default:
   buffer[0] = '?';
   buffer[1] = 0;
}

我总是按照预期获得IPv6地址,或者如果它是IPv4连接,则如下所示::ffff:127.0.0.1

我必须更改什么,才能以127.0.0.1 (没有::ffff:-前缀)的形式显示为普通的旧IPv4地址?

谢谢泰迪

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-19 18:19:22

有两种方法可供选择:

  1. 只要从一开始就去掉这个::ffff:,并将其作为IPv4的指示器。
  2. 使用两个不同的套接字。有一些操作系统不支持IPv4和6通过一个插槽(IOW,他们总是启用V6ONLY )。特别是,WinXP会这样做。

那么只有一件事可以做:。

代码语言:javascript
复制
- Use `getaddrinfo()` with `AI_PRIVATE` for getting all local socket addresses you can have
- Use them all to create a listening socket and enable `V6ONLY` immediately, if possible
- Keep their descriptors in an array and use `select()` et al to determine which of them to call `accept()`.

听起来比实际情况更复杂...

票数 1
EN

Stack Overflow用户

发布于 2012-12-20 01:19:49

有一个宏可以提供帮助,但只完成了一半:

代码语言:javascript
复制
  if (IN6_IS_ADDR_V4MAPPED(&serv_addr.sin6_addr)) {
        struct sockaddr_in tmpsa;
        tmpsa.sin_family = AF_INET;
        tmpsa.sin_port = 0;
        tmpsa.sin_addr.s_addr = serv_addr.sin6_addr.s6_addr32[3];
  /* process IPv4 address in tmpsa ... */
        inet_ntop (AF_INET, &tmpsa.sin_addr, buffer, size);
  } else {
  /* process IPv6 address in serv_addr.. */
        inet_ntop (AF_INET6, &serv_addr.sin6_addr, buffer, size);
  }

根据平台的不同,可能需要做一些小的修改,这里使用GNU标准。

票数 2
EN

Stack Overflow用户

发布于 2012-12-20 00:55:21

您请求将IPv4映射连接表示为实际上是IPv4的连接,代码如下:

代码语言:javascript
复制
int cli = accept( server, NULL, NULL );
int addrform = AF_INET;
setsockopt( cli, IPPROTO_IPV6, IPV6_ADDRFORM, &addrform, sizeof(addrform) );

这将需要对每个新的客户端套接字执行此操作。对于IPv6连接,它将失败;您可以忽略它,也可以先检查并仅在使用ipv4映射的客户机时调用它。

完成后,您可以调用getpeername()以获取首选格式的客户机地址信息,而不是将其作为accept()调用的一部分获取。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13949750

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档