您的位置:首页 > 移动开发

appstore审核的那些事 --2. IPv6环境下的支持

2017-01-06 11:21 169 查看
AppStore审核的时候反馈:
We discovered one or more bugs in your app when reviewed on iPad and iPhone running iOS 10.2 on Wi-Fi connected to an IPv6 network.

因此我需要修改IPv6环境下的支持。使用了socket的时候仅支持了IPv4
1.在网络连通性检测的时候使用了socket:
原来的表现:在IPv6环境下显示网络连接不通,包括直接IP访问(192.168.1.22)和域名访问(baidu.com
修改后结果:IP访问和域名访问都显示可以成功访问(都可以直接获取的IPv6格式的地址)
原理不再赘述,详见最下面的链接
主要修改的是:
1) gethostbyname —> getaddrinfo
2)根据getaddrinfo做IPv4和IPv6的区分
3)添加sockaddr_in6等IPv6相关内容
修改后代码:
/**
@brief 测试连接
*/
+ (void)testConnection:(NSString*)host port:(NSNumber*)port compelete:(nullable void(^)(BOOL isSuccess))compelete {
if(!host){
compelete(NO);
}
NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
[operationQueue addOperationWithBlock:^{
// NSString * host =@"123.33.33.1";
// NSNumber * port = @1233;

// 创建 socket
int socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == socketFileDescriptor) {
NSLogD(@"创建失败");
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
compelete(NO);
}];
return;
}
NSLogD(@"host %@:%@",host,port);

// 获取 IP 地址
int error, sockfd;
const char *cause = NULL;
struct addrinfo hints, *res, *res0;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_DEFAULT;
error = getaddrinfo([host UTF8String], "http", &hints, &res0);
NSLogD(@"getaddrinfo %d",error);

if (0 != error) {
close(socketFileDescriptor);
NSLogD(@"%@",@"无法解析服务器的主机名");
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
compelete(NO);
}];
return;
}
sockfd = -1;
struct sockaddr_in *addr;
struct sockaddr_in6 *addr6;
char ipbuf[28];
for (res = res0; res; res = res->ai_next) {
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0) {
cause = "socket";
continue;
}
if(AF_INET6==res->ai_family){
addr6 = (struct sockaddr_in6 *)res->ai_addr;
addr6->sin6_port = htons([port intValue]); // 修改端口号
printf("%s\n", inet_ntop(AF_INET6, &addr6->sin6_addr, ipbuf, 28));
// 连接 socket
if (connect(sockfd, (struct sockaddr *) addr6, sizeof(*addr6)) < 0) {
cause = "connect v6";
close(sockfd);
sockfd = -1;
continue;
}
}else{
addr = (struct sockaddr_in *)res->ai_addr;
addr->sin_port = htons([port intValue]);
printf("%s\n", inet_ntop(AF_INET, &addr->sin_addr, ipbuf, 16));
// // 设置为非阻塞
// fcntl(sockfd,F_SETFL,fcntl(sockfd,F_GETFL,0)|O_NONBLOCK);
// 连接 socket
if (connect(sockfd, (struct sockaddr *) addr, sizeof(*addr)) < 0) {
// if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
cause = "connect";
close(sockfd);
sockfd = -1;
continue;
}
}
break; /* okay we got one */
}
if (sockfd < 0) {
/*NOTREACHED*/
NSLog(@"error cause %s", cause);
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
compelete(NO);
}];
return;
}
NSLogD(@"连接成功%@",host);
close(sockfd);
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
compelete(YES);
}];

}];
}
调用访问网络的方法:
[Utils testConnection:service port:@(port) compelete:^(BOOL isSuccess) {
if(isSuccess){
// success
}else{
// failure
}
}];


2.在访问服务端接口的时候用了socket
与上述方法相同,只不过根据需求设置成阻塞/非阻塞的,看最后是否需要调用close(sockfd);关闭此连接

PS. 
1.IPv6环境的搭建
1)用wifi:http://www.jianshu.com/p/632d995749e1
2)用4G:http://www.cnblogs.com/SUPER-F/p/IPV6.html
2.官方指导和使用
https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html#//apple_ref/doc/uid/TP40010220-CH213-SW11

3.讲的比较详细的socket使用:https://github.com/WeMobileDev/article/blob/master/IPv6%20socket%E7%BC%96%E7%A8%8B.md#%E6%B7%B7%E5%90%88%E7%9A%84%E6%96%B9%E6%A1%88mac-osioslinuxandroid%E9%83%BD%E6%94%AF%E6%8C%81windowswp%E5%BE%85%E6%B5%8B%E8%AF%95
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: