上面2个主要是说明证书申请和打包上传及审核流程,本文主要内容是解决app store上架的排名第三问题(据说是上架问题排行榜第三,也不知道是不是真的,姑且就当作是真的呗)。
如果项目中仅使用了http或https协议,那只需要把ip地址用域名就行了,另外尽量用nssession之类系统提供的api,毕竟iOS系统自己肯定是支持ipv6的(好像很多做iOS开发的都喜欢用第三方http库,个人觉得这么简单的东西,也没啥必要)。简单封装一下就可以了。
typedef void (^HttpHandler)(NSData* _Nullable data, NSURLResponse* _Nullable res, NSError* _Nullable e); + (void) httpAsAsynchronousRequestUrl:(NSString *)spec post:(NSString *)data httpHandler:(HttpHandler)handler { NSURL *url = [NSURL URLWithString:spec]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; if(data != nil){ request.HTTPMethod = @"POST"; request.HTTPBody = [data dataUsingEncoding:NSUTF8StringEncoding]; }else{ request.HTTPMethod = @"GET"; } [request setTimeoutInterval:15]; //application/json [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; //NSLog(@"%@",spec); NSURLSession *session = [NSURLSession sharedSession]; // 由于要先对request先行处理,我们通过request初始化task NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:handler]; [task resume]; } + (NSData*) httpAsSynchronousRequestUrl:(NSString *)spec post:(NSString* _Nullable)data { NSURL *url = [NSURL URLWithString:spec]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; if(data != nil){ request.HTTPMethod = @"POST"; request.HTTPBody = [data dataUsingEncoding:NSUTF8StringEncoding]; }else{ request.HTTPMethod = @"GET"; } //application/json [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; //NSLog(@"%@",spec); //NSURLSession *session = [NSURLSession sharedSession]; NSData* response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; return response; }
一个同步&异步2个方法
如果项目中不仅有http(https)协议,还有socket,也是需要做ipv6的支持的
下面是oc代码
//获取不同网络环境的IP地址 + (NSString *)getSockAddrIPString:(const struct sockaddr *)sa; //根据不同的网络环境设置端口 + (void)setPort:(uint16_t)port forSockAddr:(const struct sockaddr *)sa; @end @implementation IPv6Tester + (NSString *)getSockAddrIPString:(const struct sockaddr *)sa { NSString *result = @""; sa_family_t netType = sa->sa_family; if(netType == AF_INET) { char ipv4_str_buf[INET_ADDRSTRLEN] = {0}; struct sockaddr_in *v4sa = (struct sockaddr_in *)sa; inet_ntop(AF_INET,// &(v4sa->sin_addr),// ipv4_str_buf,// sizeof(ipv4_str_buf)); result = [[NSString alloc] initWithCString:ipv4_str_buf encoding:NSUTF8StringEncoding]; } else if(netType == AF_INET6) { char ipv6_str_buf[INET6_ADDRSTRLEN] = {0}; struct sockaddr_in6 *v6sa = (struct sockaddr_in6 *)sa; inet_ntop(AF_INET6,// &(v6sa->sin6_addr),// ipv6_str_buf,// sizeof(ipv6_str_buf)); result = [[NSString alloc] initWithCString:ipv6_str_buf encoding:NSUTF8StringEncoding]; } return result; } + (void)setPort:(uint16_t)port forSockAddr:(const struct sockaddr *)sa { sa_family_t netType = sa->sa_family; if(netType == AF_INET) { struct sockaddr_in *v4sa = (struct sockaddr_in *)sa; v4sa->sin_port = htons(port); } else if(netType == AF_INET6) { struct sockaddr_in6 *v6sa = (struct sockaddr_in6 *)sa; v6sa->sin6_port = htons(port); } } + (void)testMain { struct addrinfo res0; struct addrinfo *res1 = 0; struct addrinfo *res2 = 0; const char *cause = 0; //这里更换成你的服务器ip地址 const char *address = "xxx.xx.xx.xxx"; //这里是服务端口 NSUInteger port = 8084; memset(&res0, 0, sizeof(res0)); res0.ai_family = PF_UNSPEC; res0.ai_socktype = SOCK_STREAM; res0.ai_flags = AI_DEFAULT; int error = getaddrinfo(address, NULL, &res0, &res1); if (error) { //没有连接上 errx(1, "%s", gai_strerror(error)); } int s = -1; for (res2 = res1; res2; res2 = res2->ai_next) { s = socket(res2->ai_family, res2->ai_socktype, res2->ai_protocol); if (s < 0) { cause = "socket"; continue; } struct sockaddr *addr = (struct sockaddr *)res2->ai_addr; [TestIPV6 setPort:(uint16_t)port forSockAddr:addr]; NSString *ipString = [TestIPV6 getSockAddrIPString:addr]; NSLog(@"尝试连接地址 : %@", ipString); if (connect(s, res2->ai_addr, res2->ai_addrlen) < 0) { cause = "connect"; close(s); s = -1; continue; } break; } if(s >= 0) { UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"提示" message:@"连接成功" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"好的", nil]; [alertview show]; } else { //没有连接上 UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"提示" message:@"连接失败" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"好的", nil]; [alertview show]; err(1, "%s", cause); } freeaddrinfo(res1); } @end
如果纯C环境稍微改装下
#ifndef IPV6_h #define IPV6_h #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> #include <err.h> #include <string.h> static std::string getSockAddrIPString(const struct sockaddr * sa) { std::string result; sa_family_t netType = sa->sa_family; if(netType == AF_INET) { char ipv4_str_buf[INET_ADDRSTRLEN] = {0}; struct sockaddr_in *v4sa = (struct sockaddr_in *)sa; inet_ntop(AF_INET,// &(v4sa->sin_addr),// ipv4_str_buf,// sizeof(ipv4_str_buf)); result = ipv4_str_buf; } else if(netType == AF_INET6) { char ipv6_str_buf[INET6_ADDRSTRLEN] = {0}; struct sockaddr_in6 *v6sa = (struct sockaddr_in6 *)sa; inet_ntop(AF_INET6,// &(v6sa->sin6_addr),// ipv6_str_buf,// sizeof(ipv6_str_buf)); result = ipv6_str_buf; } return result; } static void setPort(int port,const struct sockaddr * sa) { sa_family_t netType = sa->sa_family; if(netType == AF_INET) { struct sockaddr_in *v4sa = (struct sockaddr_in *)sa; v4sa->sin_port = htons(port); } else if(netType == AF_INET6) { struct sockaddr_in6 *v6sa = (struct sockaddr_in6 *)sa; v6sa->sin6_port = htons(port); } } static std::string convertServerAddr(const char* cpIpAddr,int nPort) { std::string server; if(strcmp(cpIpAddr,"0.0.0.0") == 0)return std::string("0.0.0.0");//过滤无效的ip地址 struct addrinfo res0; struct addrinfo *res1 = 0; struct addrinfo *res2 = 0; memset(&res0, 0, sizeof(res0)); res0.ai_family = PF_UNSPEC; res0.ai_socktype = SOCK_STREAM; res0.ai_flags = AI_DEFAULT; int error = getaddrinfo(cpIpAddr, NULL, &res0, &res1); if (error) { //没有连接上 errx(1, "%s", gai_strerror(error)); } int s = -1; for (res2 = res1; res2; res2 = res2->ai_next) { s = socket(res2->ai_family,res2->ai_socktype,res2->ai_protocol); if (s < 0)continue; struct sockaddr *addr = (struct sockaddr *)res2->ai_addr; setPort(nPort,addr); server = getSockAddrIPString(addr); printf("原地址:%s=>新地址:%s\n",cpIpAddr, server.c_str()); close(s); break; } freeaddrinfo(res1); return server; } #endif /* IPV6_h */
必须要引入的头文件,调用convertServerAddr方法就行了。最后就是搭建一个IPV6的无线环境,用真机测试。环境搭建教程:https://www.jianshu.com/p/632d995749e1 相对简单。
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (3)
-
std::string ip = convertServerAddr(pIpstr,iPort);域名转ipv6地址
if(strcmp(m_sBakAddr,pIpstr)!=0 || m_iBakPort!=iPort) { strcpy(m_sBakAddr,pIpstr); m_iBakPort =iPort; std::string ip = convertServerAddr(pIpstr,iPort); m_ServerAddr =tcp::endpoint(address::from_string(ip.c_str()),iPort); return 1; }
原地址:*.62.204.*=>新地址:2001:2:0:1baa::*:*
站点信息
- 文章2295
- 用户1336
- 访客10160089
每日一句
Success is how high you bounce when you hit bottom.
成功是你跌到谷底时反弹的高度。
成功是你跌到谷底时反弹的高度。
新会员