关于这几天使用IOS的ASYNCSOCKET完成无限后台的过程_ios gcdasyncsocket 进入后台运行-程序员宅基地

技术标签: iOS网络  asyncSocket  心跳包  

这几天用了下ASyncSocket完成前后台即时通讯,当时有想过用消息推送的技术实现的,可是后来想到消息推送的不可靠性还是算了。于是使用了tcp/ip实现后台主动发送数据给前台的功能。

最开始设计后台的时候,我有考虑到数据量比较大的问题,所以数据大的时候我会使用分包和组包的功能去实现。TCP/IP在传输数据的时候,一般不会大于1500字节,所以我每512字节分了

一个包。然后当一次性数据包接收太多的时候,就出现了粘包的问题。因为我在数据传输的时候使用的是json,每一个分包都是由{}括起来的,所以我就想着在包头上加上一段基本不会重复

的分割字符串,然后服务器接收到分包的时候每次都根据这个字符串分割一下,第一次分割的时候第一行绝对是空字符串 例如:@Hinagiku{“Name”=“桂雏菊”}, 我分割出来结果是:

“”,“桂雏菊”,所以说第一行我就可以直接跳过,每次取分包的时候从第二行开始取。然后后台根据包的ID号,序号进行组包。如果当前分包在5分钟内没有接收完毕,就代表当前分包接收失败

了,要求客户端或服务器重新发送。粘包问题解决完毕之后,我开始实现心跳包功能,当时想的是,每隔1分钟发一次心跳包,服务器放一个线程。每隔几秒钟判断一次,当前的所有TCP连接的

最后一次访问时间是多少号,如果超过了这个时间则断开当前连接。

  实现完成之后,我开始着手无限后台功能的实现。在这里我就不说无限后台有哪几种实现方式了,好麻烦,我使用的VOIP模式。我使用的是在code4app上下载的AsyncSocket这个开源类库,

和GCDAsyncSocket的用法是一样的。开始的时候实现的比较轻松,客户端和服务器的连接和数据传输很快就完成了。后来在实现无限后台的时候,出现了一个很奇怪的问题:我在调试状态运行

程序的时候,程序隐藏到后台的时候的确是可以无限运行的,并且TCP连接没有断开。但是我非调试状态运行的时候,TCP连接在3分钟之后就断掉了。 出现这个问题后我找了整整一天的时候,后来

找到了原因,因为我注释掉了一行代码,所以导致TCP连接会被断开。按道理,实现无限后台有以下几个步骤,首先在plist文件中的Required background modes这一项中新增以下两项(默认

项目中是没有这一项的,需要手动添加):App play audio or streams audio/video using AirPlay和App provides Voice over IP services 。IOS7中没有这么麻烦,可以直接点击项目文件,

勾选以下两项:

然后在AsyncSocket.m中,修改以下方法:

 - (BOOL)createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr

- (BOOL)createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr

 

拷贝以下代码到这个方法中

CFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);
CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);
 CFReadStreamSetProperty(theReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
 CFWriteStreamSetProperty(theWriteStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);

 [(NSInputStream *)theReadStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType]; //(这里需不需要加上我不清楚,反正加上也不会报错。。。)
 [(NSOutputStream *)theWriteStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType]; //(这里需不需要加上我不清楚,反正加上也不会报错。。。)

然后在AppDelegate的- (void)applicationDidEnterBackground:(UIApplication *)application这个事件中写入以下代码:

复制代码

- (void)applicationDidEnterBackground:(UIApplication *)application {       BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{            [self heartbeat];    }];    if (backgroundAccepted)    {        NSLog(@"backgrounding accepted");    } }

复制代码


[self heartbeat] 是我写的一个心跳包的方法,这段代码的意思是:每隔10分钟向服务器发送一次心跳包,保证你的TCP连接是正常的。

由于我以前在applicationDidEnterBackground这个事件中写入了这样的代码,所以才会出现那个奇怪的问题:

 

 

复制代码

- (void)applicationDidEnterBackground:(UIApplication *)application {       BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{            [self backgroundhandler];    }];    if (backgroundAccepted)    {        NSLog(@"backgrounding accepted");    }      [self backgroundhandler]; }-(void) backgroundinghandler{NSLog(@"### -->backgroundinghandler");        UIApplication*  app = [UIApplication sharedApplication];    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{        //[app endBackgroundTask:bgTask];    }];    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        while (1) {            NSLog(@"counter:%d", count++);            NSLog(@"timer:%f", [app backgroundTimeRemaining]);            sleep(1);        }    });}

复制代码

这样的代码其实就是为了向后台借更多的时间,但是我们因为使用VOIP后完全不需要借时间了,在TCP监听到消息的时候,程序会从休眠中唤醒10秒左右,所以说在这10秒内我们把接收到的消息处理完就行了。这是网上教程写出来的一个误区,我们使用

 VOIP的时候完全没有必要再去借时间了。

 

我把下面的这段代码改成了上面的那段代码后,我程序挂起到后台以后,我还是收不到服务器发送到的消息。我感觉我的代码没错,到底是哪里出了错误呢。找了几个小时之后,我无意中看到一段提醒:后台监听消息一定要在真机中运行,在模拟器中是监听

不到的。后来我把测试环境改成了ipad,果然就收到消息了,然后发现我自己的愚蠢。因为ipad拿着太麻烦了,所以我用的是模拟器测试的。 哎,以后大家测试这种代码还是都用真机吧,不要跟我一样被坑了。。。

 

本篇文章差不多也就记录到这里了,我还是一个ios新人,有一些理解可能不正确,希望大家指点出来共同学习。



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhaojian3513012/article/details/46792937

智能推荐

php defined or define,define与defined有什么区别-程序员宅基地

文章浏览阅读555次。define与defined的区别有:1、define是用来定义一个常量的且常量被定义后就不能再改变或取消;2、defined是检测常量是否被定义,若存在返回true,不存在返回false。【推荐教程:PHP教程】define与defined的区别definedefine是用来定义一个常量,常量表示的就是全局范围,因此不需要考虑作用域就可以直接在脚本中的任何地方进行访问。但是需要注意的一点是常量一..._php defined('') or define('', ");

【三年面试五年模拟】算法工程师的独孤九剑秘籍(第十一式)_算法独孤九剑-程序员宅基地

文章浏览阅读491次。2022年平安夜,和WeThinkIn的文章更配哦_算法独孤九剑

oracle和mysql使用区别大吗_Oracle和MySQL在使用上的区别-程序员宅基地

文章浏览阅读825次。1、 Oracle是大型数据库而MySQL是中小型数据库,MySQL是开源的而Oracle的价格非常高。2、 Oracle支持大并发,大访问量。3、 安装所用的空间差别也是很大,MySQL安装完后用100多M而Oracle有3G左右,而且使用的时候Oracle占用特别大的内存空间和其他机器性能。4、 在使用上的一些区别:1)、主键:MySQL一般使用自动增长类型,在创建表时,只要指定表的主..._oracle数据库与mysql的操作一样吗

基于51单片机微波炉简易控制仿真设计数码管显示proteus仿真+程序+设计报告+讲解视频)-程序员宅基地

文章浏览阅读823次,点赞23次,收藏13次。基于51单片机微波炉简易控制仿真设计数码管显示( proteus仿真+程序+设计报告+讲解视频)仿真图proteus7.8及以上程序编译器:keil 4/keil 5编程语言:C语言设计编号:S0071。

人脸识别~警察领域-程序员宅基地

文章浏览阅读214次。比如,我一朋友做显著性检测,如果只在实验中通过搭建框架、训练测试,得出结果,那只是看到一个理论的表现,但是我朋友实验室有专门的显著性眼动仪,其可以通过现有模型的辅助,去人为进行实际实验,观察每一幅图像的显著性点及区域(说到这,我们平台准备下期为大家带来显著性检测),所以,本次分享的文献有些乏味,但希望做人脸领域的小伙伴,可以通过实际生活中的一些经验,通过数学的方式应用到模型当中,对实际场景的检测或识别有一定的提升。在没有目标的试验中,参与者可以引起正确的反应(正确的拒绝)或错误地识别错误者的脸(假阳性)。

拉扎维模集笔记-程序员宅基地

文章浏览阅读1.1k次,点赞6次,收藏35次。1.ro是什么答:ro是沟长调制效应的等效电阻,值约为1/(λ*Id)。2.η是什么答:η是体效应的影响3.PVT是什么答:P是工艺影响;V是电压影响;T是温度影响;L是负载影响。_模集

随便推点

【船舶】基于simulnk模拟船舶动力定位-程序员宅基地

文章浏览阅读985次,点赞21次,收藏22次。船舶动力定位(DP)是一种先进的船舶控制系统,能够使船舶在没有任何锚泊或系泊的情况下保持其位置和航向。DP 系统通过使用推进器、舵机和传感器来实现这一目标。DP 系统通常用于需要在海上进行精确操作的船舶,例如钻井船、起重船、铺管船和科学研究船。DP 系统还可以用于在恶劣天气条件下保持船舶的安全,例如在飓风或台风期间。

ThreadX在mdk(AC5)中的移植_threadx移植-程序员宅基地

文章浏览阅读771次。Threadx是由 Express Logic 公司开发的一款实时操作系统(RTOS),2019年被微软收购,成为了微软的一款Azure RTOS。在2020年,ThreadX也加入了开源大军,将ThreadX内核及其各大组件开源免费。ThreadX可以说是一款发展非常迅猛的RTOS,相信最近两年有了解它的朋友都能理解。2019年:被微软收购;2020年:免费开源;2021年:上线中文版手册;Azure RTOS ThreadX 文档。_threadx移植

matlab-m文件常用积分函数-ode45含有时变参数用法/菜鸟理解4_simulink积分器问题-程序员宅基地

文章浏览阅读7.6k次,点赞53次,收藏92次。目录写在前面ode45积分器带有时变参数的ode45积分总结写在后面写在前面本人大四狗一名,最近在帮实验室肝项目,毕设用的强化学习暂且放下了一段时间,所以没有更新。在给实验室打工的过程中,遇到了一个需要用到时变参数的微分方程组,解决这种问题利用simulink很好解决,但是项目要求使用m文件进行编程,在以往的学习中,m文件的积分函数一般就是使用ode45,变步长积分器。常用的语法是[t,y] = ode45(@odefun,tspan,y0)[t,y] = ode45(@odefun,tspan,y_simulink积分器问题

xenser服务器虚拟化,Citrix服务器虚拟化之七Xenserver虚拟机复制(最新整理)-程序员宅基地

文章浏览阅读465次。《Citrix服务器虚拟化之七Xenserver虚拟机复制(最新整理)》由会员分享,可在线阅读,更多相关《Citrix服务器虚拟化之七Xenserver虚拟机复制(最新整理)(3页珍藏版)》请在人人文库网上搜索。1、Citrix 服务器虚拟化之七 Xenserver 虚拟机复制XenServer 包含两种克隆虚拟机的方法,完整复制和快速复制。完整复制就是将虚拟机完整地复制一份,复制速度取决于存储性..._xenserver没有xentools

[STM32WBA]【STM32WBA52CG测评】开箱&呼吸灯-程序员宅基地

文章浏览阅读294次。支持 BLE 5.3 全部功能,比如: long-range,1/2M 传输速率、 LE audio、扩展广播, AOD/AOA,.LE增强版连接更新功能,BLE 以及 802.15.4的私有协议,支持matter相关应用。另外,因为它是基于Cotex-M33核,具有更高的安全性能,支持SESIP-L3, 同时基于新一代ST MCU低功耗平台,具有更优的低功耗性能。本开发板带的外部晶振是32M的。灯最亮的时候高电平时间为0,为了30次将0变成500,每次让duty_num增大500/30,就是17。_stm32wba52

静态网页设计——电影推荐网(HTML+CSS+JavaScript)_电影推荐网页代码-程序员宅基地

文章浏览阅读999次,点赞26次,收藏21次。声明:该文章只是做技术分享,若侵权请联系我删除。!!使用技术:HTML+CSS+JS(静态网页设计)主要内容:对好看的电影进行推荐。该页面使用p标签和人span标签嵌入许多文本,将关于网站主题的介绍全部写到网页中,文字排版根据字数来进行,使用不会出现不协调的情况。在文字旁边,使用img标签嵌入一些图片,使得网页整体更加的美观。_电影推荐网页代码

推荐文章

热门文章

相关标签