支持苹果IPV6 ONLY 的socket 修改方法
首先别错误理解以为app 必须支持 ipv6 的服务端, 只需要支持 ipv6的客户端需要访问 ipv4 的服务端。
目前需要经过 NAT64 转换就能达到目的,客户端只需要支持该转换就能实现, 在OS X的系统上是的wifi 共享有支持 NAT64转换,提供了这个功能就方便了我们可以使用手机链接 OS X上的热点模拟这个测试环境。
我们代码上所需要完成的事情:
1.客户端需要链接的ip地址(ipv4) 通过转换。
getaddrinfo //方法可以转换为 ipv6 的地址。 struct addrinfo hints, *res, *res0; memset(&hints, , sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; #if (PLATFORM == PLATFORM_WIN32) hints.ai_flags = AI_PASSIVE; #else hints.ai_flags = AI_DEFAULT;
18 #endif int error = getaddrinfo(pServerIP, "http", &hints, &res0);
2.经过转换后我们可以判断 ai_family 兼容 非NAT64 转换的网络环境与 NAT64转换的网络环境 下进行 socket的链接:
struct sockaddr_in addr_in; struct sockaddr_in6 addr_in6; int connect_ret; for (res = res0; res; res = res->ai_next) { connect_ret = -; tempSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (tempSocket < ) { continue; } if(AF_INET == res->ai_family){ addr_in = *((struct sockaddr_in *)res->ai_addr); addr_in.sin_port = htons(ServerPort); connect_ret = connect(tempSocket, (struct sockaddr *)&addr_in, res- >ai_addrlen); }else if(AF_INET6 == res->ai_family){ addr_in6 = *((struct sockaddr_in6 *)res->ai_addr); addr_in6.sin6_port = htons(ServerPort); connect_ret = connect(tempSocket, (struct sockaddr *)&addr_in6, res->ai_addrlen); } if (connect_ret < ) { cause = "connect"; #if (PLATFORM == PLATFORM_WIN32) closesocket(tempSocket); #else close(tempSocket); #endif tempSocket = -; continue; } break; }
OK,这样就支持 ipv6 对 ipv4 的网络 而且兼容 普通 ipv4 对 ipv4 的网络。
上面是没有考虑链接时候客户端会进入卡死状态直到链接成功, 因为加上去代码会复杂点,为了好看就没有加上, 真实项目中需要改为非阻塞模式, 通过select 来判断是否connect成功。
下面是加上非阻塞模式:
int tempSocket = -;
struct addrinfo hints, *res, *res0;
int error;
const char *cause = NULL; memset(&hints, , sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(pServerIP, NULL, &hints, &res0);
if (error) {
CCLOG("getaddrinfo error:%d", error);
return false;
} struct sockaddr_in addr_in;
struct sockaddr_in6 addr_in6;
for (res = res0; res; res = res->ai_next) {
tempSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (tempSocket < ) {
cause = "socket";
continue;
} #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
// 设定 非阻塞
unsigned long tmepOption = ; //0:阻塞
ioctlsocket(tempSocket, FIONBIO, &tmepOption);
#else
// 设定 非阻塞
int flag = fcntl(tempSocket, F_GETFL, );
fcntl(tempSocket, F_SETFL, flag | O_NONBLOCK);
#endif if(AF_INET == res->ai_family){
addr_in = *((struct sockaddr_in *)res->ai_addr);
addr_in.sin_port = htons(ServerPort);
connect(tempSocket, (struct sockaddr *)&addr_in, res->ai_addrlen);
}else if(AF_INET6 == res->ai_family){
addr_in6 = *((struct sockaddr_in6 *)res->ai_addr);
addr_in6.sin6_port = htons(ServerPort);
connect(tempSocket, (struct sockaddr *)&addr_in6, res->ai_addrlen);
} fd_set fset;
FD_ZERO(&fset);
FD_SET(tempSocket, &fset); timeval timeout;
timeout.tv_sec = ; // 1.5秒超时, 上层逻辑会尝试3次 >> 1.5 * 3
timeout.tv_usec = ;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
socklen_t len = sizeof(error);
#else
int len = sizeof(error);
#endif
if( select(tempSocket+, NULL, &fset, NULL, &timeout) > )
{
if (FD_ISSET(tempSocket, &fset))
{
getsockopt(tempSocket, SOL_SOCKET, SO_ERROR, (char *)&error, &len);
if(error == ){
break;
}
}
} #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
closesocket(tempSocket);
#else
close(tempSocket);
#endif
tempSocket = -; } if (tempSocket < ) {
CCLOG("connect server error:%d", tempSocket);
goto RETURN_FALSE;
} if(false){
RETURN_FALSE:
freeaddrinfo(res0);
return false;
}
支持苹果IPV6 ONLY 的socket 修改方法的更多相关文章
- 服务器配置ssl证书支持苹果ATS方法
服务器配置ssl证书支持苹果ATS方法 发布日期:2016-12-14 苹果安全工程&架构部门主管Ivan Kristic表示ATS将在今年底成为App Sotre app的必要条件,这将大幅 ...
- Linux配置支持高并发TCP连接(socket最大连接数)
Linux配置支持高并发TCP连接(socket最大连接数) Linux配置支持高并发TCP连接(socket最大连接数)及优化内核参数 2011-08-09 15:20:58| 分类:LNMP&a ...
- as关键词还有另外一个用途,那就是修改 方法 的访问控制
PHP是单继承的语言,在PHP 5.4 Traits出现之前,PHP的类无法同时从两个基类继承属性或方法.php的Traits和Go语言的组合功能类似,通过在类中使用use关键字声明要组合的Trait ...
- Oracle 11g RAC环境下Private IP修改方法及异常处理
Oracle 11g RAC环境下Private IP修改方法及异常处理 Oracle 11g RAC环境下Private IP修改方法及异常处理 一. 修改方法 1. 确认所有节点CRS服务以启动 ...
- dedecms 使noflag参数及其过滤多个属性的修改方法
noflag='h' 是代表不包含头条属性的意思,其中flag就是属性, 自定义属性值:头条[h]推荐[c]图片[p]幻灯[f]滚动[s]跳转[j]图文[a]加粗[b]. noflag过滤多个属性的修 ...
- 使用cocoapods的两个大坑的修改方法
1.报错内容: [!] The dependency `ReactiveCocoa (= 2.1.8)` is not used in any concrete target. The depende ...
- Linux网卡调优篇-禁用ipv6与优化socket缓冲区大小
Linux网卡调优篇-禁用ipv6与优化socket缓冲区大小 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一般在内网环境中,我们几乎是用不到IPV6,因此我们没有必要把多不 ...
- 迅为4412开发板QtE系统源码-屏幕横竖屏切换修改方法
迅为4412开发板QtE系统源码-屏幕横竖屏切换修改方法 详情了解:http://topeetboard.com 更多了解:https://arm-board.taobao.com/ 用户在开发板上运 ...
- Socket.BeginConnect 方法
Socket.BeginConnect 方法 (IPAddress, Int32, AsyncCallback, Object) 开始一个对远程主机连接的异步请求. 主机由 IPAddress 和端口 ...
随机推荐
- JavaSE教程-01初识Java-思维导图
图片看不清楚时: 1)可以将图片另存为图片,保存在本地来查看 2)右击在新标签中打开放大查看. 分解: 1.计算机基本概念的普及 硬件 cpu.内存.硬盘等 软件 系统级软件 Windows.Linu ...
- java基础(八章)
一. 什么是数组及其作用? 定义:具有相同数据类型的一个集合 作用:存储连续的具有相同类型的数据 二. java中如何声明和定义数组 l 声明和定义的语法: 数据类型[ ...
- Discuz插件开发之全站论坛目录结构注释
基本上新版本的discuzX系列目录结构都差不多,刚好大神整理出来了,就拿来看吧. |-- /api uc.php UCenter通信文件 |-- /api/addon ...
- XtraBackup物理备份 阿里云的Mysql备份方案
XtraBackup物理备份 Percona XtraBackup是世界上唯一的开源,免费的MySQL热备份软件,为InnoDB和XtraDB 数据库执行非阻塞备份.使用Percona XtraBac ...
- JavaScript设计模式_10_职责链模式
职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止.职责链模式的名字非常形象,一系列可能 ...
- mysql GROUP_CONCAT获取分组的前几名
比如说要获取班级的前3名,oracle 可以用 over partition by 来做.mysql就可以用GROUP_CONCAT + GROUP BY + substring_index实现. ...
- war包中少了class文件
用eclipse的maven工具打包(执行mvn clean install 和 mvn package)后,再启动wildfly, war包应该会自动复制到wildfly的deployment ...
- 马踏棋盘算法递归+回溯法实现 C语言
r为矩阵的行,c为矩阵的列 将结果输出到当前目录下的results.txt. 结果将给出:1.是否存在路径使马可以按要求走遍所有的方格: 2.解的总数: 3.程序执行的时间: #include< ...
- Itunes制作手机铃声,图文版
一.下载歌曲,选择歌曲用itunes打开,打开出现下面界面 二.设置歌曲 右键点击歌曲,找到显示简介,点击选项,截取音乐,出现下图: 截取你喜欢的部分,点击确定 点击确定后,选中该歌曲,找到左上方 文 ...
- 【Android Developers Training】 106. 创建并检测地理围栏
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...