支持苹果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 和端口 ...
随机推荐
- javascriptDOM节点
DOM把层次中的每一个对象都称之为节点(NODE),以HTML超文本标记语言为例:整个文档的一个根就是<html>,在DOM中可以使用 document.documentElement来访 ...
- Python给小说做词云
闲暇时间喜欢看小说,就想着给小说做词云,展示小说的主要内容.开发语言是Python,主要用到的库有wordcloud.jieba.scipy.代码很简单,首先用jieba.cut()函数做分词,生成以 ...
- C#中switch的使用
今天在网上看到有人给出这么一个程序需求,博主就拿来回忆回忆C#中switch的用法 程序需求如下: 根据星期几(一 ~日) ,输出特价菜“一”.“二”.“三”,输出“干煸扁豆6元.”“四”.“五”,输 ...
- C++判断一个数字是否为质数
关于素数的算法是程序竞赛比较重要的数论知识,我们来看通常会使用的几个算法. 我们先来复习几个基本概念: 质数:对于大于1的自然数,若除了1和它本身,没有别的因数,则称这个数为质数,质数也叫素数.反之, ...
- Jmeter-WINDOWS下的配置部署
前提:已配置安装JDK环境及已部署TOMCAT. 解压apache-jmeter-2.9.zip文件至目录,我的是D:\Program Files目录. 点击我的电脑----属性----高级----环 ...
- v9更新栏目缓存提示PHP has encountered a Stack overflow解决方法
原因: 客户在把一些栏目删除或者新增栏目时没更新栏目缓存导致v9_category表里有原来的垃圾信息,多余的表. 解决方法:通过phpmyadmin找到栏目表出错的条目,修改错误信息. 具体步骤: ...
- 关于对WEB标准以及W3C的理解与认识问题
web标准简单来说可以分为结构.表现和行为.其中结构主要是有HTML标签组成.或许通俗点说,在页面body里面我们写入的标签都是为了页面的结构.表现即指css样式表,通过css可以是页面的结构标签更具 ...
- HTML特殊布局--------双飞翼布局
今天看到以前写的一篇布局的例子分享给大家,双飞翼布局. 什么是双飞翼布局?? 1.三列布局,中间宽度自适应,两边固定宽度; 2.中间栏在浏览器中优先展示渲染: 双飞翼布局的原理: 中间的盒子定100% ...
- js函数一些小的知识点
var scope="123"; function aa(){ console.log(scope);//undefind var scope="234"; c ...
- PHP提取字符串中的所有汉字
<?php $str = 'aiezu.com 爱E族, baidu.com 百度'; preg_match_all("#[\x{4e00}-\x{9fa5}]#u", $s ...