c - C 套接字双栈 ss_family 始终 IPv6
问题描述
使用accept()
orgetpeername()
时,sockaddr_storage
总是有ss_family=AF_INET6
:
struct sockaddr_storage address = {0};
socklen_t sockaddrlen = sizeof(address);
int client = accept(sock, (struct sockaddr*)(&address), &sockaddrlen);
if (client < 0) {
perror("Unable to accept");
exit(EXIT_FAILURE);
}
if( address.ss_family==AF_INET6 ){
std::cout << "IPv6" << std::endl;
} else {
std::cout << "IPv4" << std::endl;
}
我觉得它与创作有关:
s = socket(AF_INET6, SOCK_STREAM, 0);
或绑定
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(port);
addr.sin6_addr = in6addr_any;
if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
我怎样才能得到ss_family
更正,或以另一种方式告诉它是什么类型的 IP?
解决方案
双栈套接字是 IPv6 套接字,仅支持 IPv4,因此其 IP 地址将始终是AF_INET6
地址。但是,对于 IPv4 连接,这些地址将是IPv4 映射的 IPv6 地址。
混合双栈 IPv6/IPv4 实现识别一类特殊的地址,即 IPv4 映射的 IPv6 地址。这些地址通常使用标准 IPv6 格式的 96 位前缀编写,其余 32 位使用 IPv4 的习惯点十进制表示法编写。
该组中的地址由 80 位前缀的 0 组成,接下来的 16 位是 1,其余的最低有效 32 位包含 IPv4 地址。例如 ::ffff:192.0.2.128 表示 IPv4 地址 192.0.2.128。另一种格式,称为“与 IPv4 兼容的 IPv6 地址”,是 ::192.0.2.128;但是,此方法已被弃用。
您需要明确检测到,请参阅如何从 IPv4 映射的 IPv6 地址解析 IPv4 地址?, 例如 :
#ifndef IN6_IS_ADDR_V4MAPPED
#define IN6_IS_ADDR_V4MAPPED(a) \
((((a)->s6_words[0]) == 0) && \
(((a)->s6_words[1]) == 0) && \
(((a)->s6_word[2]) == 0) && \
(((a)->s6_word[3]) == 0) && \
(((a)->s6_word[4]) == 0) && \
(((a)->s6_word[5]) == 0xFFFF))
#endif
struct sockaddr_storage address = {0};
socklen_t sockaddrlen = sizeof(address);
int client = accept(sock, (struct sockaddr*)(&address), &sockaddrlen);
if (client < 0) {
perror("Unable to accept");
exit(EXIT_FAILURE);
}
if (address.ss_family == AF_INET6){
struct sockaddr_in6 *addr = (struct sockaddr_in6*)(&address);
if (IN6_IS_ADDR_V4MAPPED(&(addr->sin6_addr))) {
std::cout << "IPv4 (mapped)" << std::endl;
} else {
std::cout << "IPv6" << std::endl;
}
} else {
std::cout << "IPv4" << std::endl;
}
推荐阅读
- javascript - 如何知道是否按下了后退/前进而不是 vue/vue-router 中的手动路由器推送?
- html - 从 HtmlService 输入修改现有日历事件
- c# - 如何在 WPF 中获得正确的屏幕 DPI?
- nginx - 如何设置 Google VM(实例分组)、https 负载均衡 w/CDN,以便后端解析域?
- java - 如何在java中调用带有另一个类的参数的方法?
- python - 有没有一种方法可以在训练期间找到 Tensorflow/Keras 层输入的最小值、最大值?
- r - 在 R 中抓取时,如何修复“10000 毫秒后连接超时”?
- jmeter - 如何在 10 分钟后退出 while 控制器
- twilio - 从硬电话更新正在进行的 Twilio 呼叫
- reactjs - 如何隐藏/显示被 ReactJS 中不同视图重用的组件的内容