移动端ios mqtt实现消息推送送 xmpp 和 mqtt 哪个更费电

iOS即时通信&(轻量级的XMPP)-MQTT_少年未老心已荒23333_新浪博客
iOS即时通信&(轻量级的XMPP)-MQTT
&在写之前,我们首先了解一下为什么iOS维护长连接需要心跳机制,首先我们知道,维护任何一个长连接都需要心跳机制,客户端发送一个心跳给服务器,服务器给客户端一个心跳应答,这样就形成客户端服务器的一次完整的握手,这个握手是让双方都知道他们之间的连接是没有断开,客户端是在线的。如果超过一个时间的阈值,客户端没有收到服务器的应答,或者服务器没有收到客户端的心跳,那么对客户端来说则断开与服务器的连接重新建立一个连接,对服务器来说只要断开这个连接即可。也就是说,如果想要完成及时聊天的功能,我们需要一个订阅和一个发布功能。​话不多说,进入主题,先去Github上down一个MQTTKit框架,网址&(需要翻墙
如果你们公司连翻墙软件都买不起 趁早辞了吧)然后把MQTTKit导入工程
&新建一个类VPKCClientManager
​VPKCClientManager.h代码如下
"MQTTKit.h"
@interface
VPKCClientManager : NSObject
+ (instancetype)sharedC
- (void)subscribeMessageWithMessageHandler:(void(^)(NSDictionary
*dict))messageH
​VPKCClientManager.m代码如下
"VPKCClientManager.h"
MQTT_HOST @"**************"//MQTT服务器网址
什么?你们后台不会搭建MQTT服务器 呵呵。。
VPKCClientManager *instance
@implementation
VPKCClientManager
& & MQTTClient
+ (instancetype)sharedClient
& //这里用到了单例 个人感觉不用也行
& & static
dispatch_once_t
& & dispatch_once(&onceToken,
& instance
(instancetype)init
//这里我们选择了把deviceId作为mqtt的clientId
& port为端口号&
username是用户名
password是密码
= [[NSUserDefaults
standardUserDefaults]
objectForKey:@"deviceId"];
& NSString
*clientId = [NSString
stringWithFormat:@"kc-%@",
deviceId];
= [[MQTTClient
initWithClientId:clientId];
& client.port
client.username
@"kidcares";
client.password
& return self;
// 重点来了& 这里是MQTT的订阅方法 在你需要的地方 调用就行
- (void)subscribeMessageWithMessageHandler:(void(^)(NSDictionary
*dict))messageHandler
& & [client
setMessageHandler:^(MQTTMessage
*message){
= [NSJSONSerialization
JSONObjectWithData:message.payload
options:NSJSONReadingAllowFragments
error:nil];
& messageHandler(json);
connectToHost:MQTT_HOST
completionHandler:^(MQTTConnectionReturnCode
(code == ConnectionAccepted)
& & [client
subscribe:client.clientID
withCompletionHandler:nil];
然后在你要用的控制器中导入#import
"VPKCClientManager.h"
创建一个对象static
VPKCClientManager
clientManager
= [VPKCClientManager
sharedClient];//初始化
这里就是MQTT的订阅方法 这个方法执行后 在MQTT服务器上就可以看到你的设备
&dict就是从MQTT服务器传下来的内容
&[clientManager
subscribeMessageWithMessageHandler:^(NSDictionary
[clientManager
subscribeMessageWithMessageHandler:^(NSDictionary
{//因为MQTT可以有多种用处,为了区分各个功能这里我们选择了遍历dict
根据key来判断如何做出响应
([key isEqualToString:@"shoutResult"])
([key isEqualToString:@"chat"])
& & NSDictionary
* chat = [dict valueForKey:@"chat"];
& & playurl
= [chat valueForKey:@"fileUrl"];//这里取出服务器文件的地址
= [chat valueForKey:@"fileRunningTime"];
& //这个是文件下载的封装方法 下面会有介绍
& & [self.audio
downloadTaskURL:playurl
completion:^(NSURL
*fileplay) {
performSelectorOnMainThread:@selector(refreshtable:)
withObject:fileplay
waitUntilDone:NO];//因为AFN下载涉及到多线程问题,如果不采用主线程加载,UI效果不会刷新
& self.url
至此 MQTT订阅部分完成了 &下面我们来说说MQTT的发布
新建一个类VPKCPush&
VPKCPush.h代码如下
"VPKCPushModel.h"
@interface
VPKCPush : NSObject
+ (void)pushMessageParameters:(VPKCPushModel
*)param success:(void
(^)(NSString
*msgId))success failure:(void
(^)(NSInteger
statusCode))
VPKCPush.m代码如下
​#import
"VPKCPush.h"
"MJExtension.h"//一个三方的直接生成keyvaluepairs的方法
@implementation VPKCPush
+ (void)pushMessageParameters:(VPKCPushModel
*)param success:(void
(^)(NSString
*msgId))success failure:(void
(^)(NSInteger
statusCode))failure
& NSString
= [KIDCARES_HOST
stringByAppendingString:@"/api/v1/push"];
& & [VPKCNetworking
POSTWithURL:url
parameters:[param
keyValues]
success:^(AFHTTPRequestOperation
*operation, id
responseObject) {
& success([responseObject valueForKey:@"msgId"]);
& & } failure:^(AFHTTPRequestOperation
*operation, NSError
& FAILURE;
这里是上传的下载的封装方法 &发送消息时调用上传
&接受消息调用下载
(void)fileUploadParameters:(VPKCFileInfo
*)file MIMEType:(NSString
*)mimeType success:(void
(^)(NSString
*))success failure:(void
(^)(NSInteger))failure
& NSString
= [KIDCARES_HOST
stringByAppendingString:@"/api/v1/file"];
& NSDictionary
= [NSDictionary
dictionaryWithObjectsAndKeys:
& & file.expiration,
@"expiration",
& & file.expires,
@"expires",
& & file.size,
& NSLog(@"~~~~~~~~~%@",param);
& AFHTTPRequestOperationManager
*manager = [VPKCNetworking managerWithURL:url
httpMethod:@"POST"];
& & [manager POST:url
parameters:param
constructingBodyWithBlock:^(id&&span
style="font-variant-ligatures: no-common- color:
#4f8187"&AFMultipartFormData&
formData) {
& [formData appendPartWithFileData:file.data
name:@"file"
fileName:file.name
mimeType:mimeType];
& NSLog(@"===========%@",formData);
& & } success:^(AFHTTPRequestOperation
*operation, id
responseObject) {
& NSString
*fileUrl = [responseObject valueForKey:@"fileUrl"];
& NSString
*fileMd5 = [responseObject valueForKey:@"fileMd5"];
& success(fileUrl, fileMd5);
& & } failure:^(AFHTTPRequestOperation
*operation, NSError
& FAILURE;
- (void)fileDownloadUrl:(NSString
*)url success:(void
(^)(NSString
*))success failure:(void
(^)(NSInteger))failure
& AFHTTPRequestOperationManager
*manager = [VPKCNetworking managerWithURL:url
httpMethod:@"GET"];
& & [manager GET:url
parameters:nil
success:^(AFHTTPRequestOperation
*operation, id
responseObject) {
= [NSString
stringWithFormat:@"%.0f.caf",
timeIntervalSinceReferenceDate]];
= [NSTemporaryDirectory()
stringByAppendingPathComponent:fileName];
*data = [NSData
dataWithData:responseObject];
& [data writeToFile:filePath
atomically:YES];
& success(filePath);
& & } failure:^(AFHTTPRequestOperation
*operation, NSError
& FAILURE;
然后在你要发布MQTT消息的控制器里导入头文件
[self.audio
uploadTaskSuccess:^(NSString
*fileMd5) {//调用文件上传的方法
& VPKCDialogue
*request = [[VPKCDialogue
& VPKCChat
*chat = [[VPKCChat
chat.fileRunningTime =
self.audio.duration;
& chat.fileUrl
& chat.fileMd5
= fileMd5;
chat.createTime =
self.audio.createTime;
*kidDevice
= [[NSUserDefaults
standardUserDefaults]
objectForKey:@"kiddeviceId"];
* kidDevicearray = [[NSArray
initWithObjects:kidDevice,
([kidDevicearray count])
= [[VPKCPushModel
initWithShout:chat
devices:@[kidDevice]];
& [request shoutParameters:model
success:^(NSString
& & sendsuccess
[[UILabel alloc]
initWithFrame:CGRectMake(self.view.frame.size.width/2-50,
self.view.frame.size.height/2,100,
sendsuccess.text=@"发送成功";
sendsuccess.textColor
= [UIColor
whiteColor];
& & sendsuccess.textAlignment=NSTextAlignmentCenter;
& & sendsuccess.backgroundColor=[UIColor
grayColor];
sendsuccess.alpha=0.7;
[self.view
addSubview:sendsuccess];
& & [NSTimer
scheduledTimerWithTimeInterval:2
target:self
selector:@selector(Timerisover:)
userInfo:nil
repeats:NO];
& } failure:^(NSInteger
statusCode) {
& & sendfail
[[UILabel alloc]
initWithFrame:CGRectMake(self.view.frame.size.width/2-50,
self.view.frame.size.height/2,100,
sendfail.text=@"发送失败";
& & sendfail.textAlignment=NSTextAlignmentCenter;
& & sendfail.backgroundColor=[UIColor
grayColor];
sendfail.alpha=0.7;
[self.view
addSubview:sendfail];
& & [NSTimer
scheduledTimerWithTimeInterval:2
target:self
selector:@selector(Timerisover1:)
userInfo:nil
repeats:NO];
& & } failure:^(NSInteger
statusCode) {
​至此MQTT订阅发布的流程已经完成
,最后强调一点,要实现两个设备之间的通信 必须保证两个设备的同时在MQTT server上在线。
少年未老心已慌1993
博客等级:
博客积分:0
博客访问:4,531
关注人气:0
荣誉徽章:  摘要:随着智能设备的快速普及和移动应用的迅猛发展,已进入移动互联网时代。消息推送是移动应用的一个显著特征,是移动互联网" />
免费阅读期刊
论文发表、论文指导
周一至周五
9:00&22:00
移动应用的消息推送与MQTT协议
2015年8期目录
&&&&&&本期共收录文章20篇
  摘要:随着智能设备的快速普及和移动应用的迅猛发展,已进入移动互联网时代。消息推送是移动应用的一个显著特征,是移动互联网时代的基础设施。苹果和谷歌都提供消息推送服务,但并不能满足企业级移动应用的推送要求。MQTT协议是由IBM提出的面向物联网的通讯协议,其简洁,高效,可靠等特征非常适合用于构建消息推送服务。文章讨论了使用MQTT协议构建消息推送服务的必要性和适用性,并指出了在具体实现上应注意的一些关键问题,同时给出了相关建议。 中国论文网 /8/view-7218604.htm  关键词:移动应用;消息推送;MQTT   1消息推送是移动应用的基础功能   现今已经从互联网时代快速进入到了移动互联网时代。根据相关资料,早在2014年,智能手机和平板电脑的销售量就已经超过了传统Pc的销售量,而且这一趋势还在不断加强,以智能手机为主的移动设备仍然在高速增长。   信息化系统建设也相应地转向移动设备,传统的基于桌面浏览器的应用系统日渐式微,移动应用(APP)已成为主流趋势。以前的热门网站不再受到人们的追捧,取而代之的是运行在手机上的各种APP0一个显著的例子是微信和QQ,同样由腾讯公司开发的社交应用,两者分别代表了移动互联网和传统互联网,微信的历史只有短短的4-5年,但其活跃用户数已经远超历史悠久的QQ。在企业内部,政府部门、事业单位内部,也纷纷调整其信息化建设,向移动应用方向倾斜,移动化已成为共识。   移动应用作为一种新的应用类型,与传统基于桌面的浏览器/服务器(Browser/Server)架构相比较,在应用场景,交互方式,开发技术等方面都有所不同。对于使用者而言,移动应用将其从电脑前解放了出来,使用者可以在任何时间,任意地点打开移动应用,浏览自己所需要的信息,或者进行相应的操作,只需设备联网即可。这种便利性使得移动应用迅速受到使用者的欢迎。而且,由于移动设备随身携带,并一直保持网络连接状态,移动应用能够做到主动的消息推送和提醒,而无需使用者不时打开应用去查看,实现了信息主动找人。   消息推送是移动应用的基础功能,是移动互联网时代的重要基础设施,是移动应用区别于传统应用的一个重要特征和优势,可以说,没有消息推送的移动应用就不能称之为移动应用。   2现有推送服务及问题   根据移动操作系统的不同,当前移动领域主要分为两个体系:苹果公司的iOS系统和由谷歌公司主导的Andriod系统。这两大阵营都意识到了移动消息推送在移动应用建设上的基础性地位,并提供了相应的推送服务,供开发者或企业用户调用。但是,无论是苹果还是谷歌的推送服务,都存在服务质量,安全性,处理容量等问题,特别是对于企业、政府等高端用户而言,这些推送服务都无法满足实际需要。   2.1苹果推送通知服务(APNS,Apple Push NotificationService)   苹果为全球范围的lOS设备提供推送通知服务。当服务的提供方(Provider)希望给某个设备上的应用推送消息时,需要调用苹果APNS提供的推送服务,将目标设备(设备令牌)和消息内容(有效载荷)传递给APNS服务,APNS会负责找到相应的目标设备,并将消息传递给该设备;该设备收到消息后,会将消息传给相应的应用APP,由APP处理消息,提醒用户。其处理过程在苹果的开发者网站有详细描述如图1所示。   从实际使用情况看,APNS服务比较稳定,一般情况下消息也能被及时传递,基本能够满足一般性消费类移动应用的需要。但是,对于具有更高消息推送要求的企业级市场,APNS就显得力不从心,具有以下问题。   (1)不保证消息到达。如果移动设备暂时无法联网,服务的提供方也可以推送消息,苹果会负责暂时保存该消息;当设备再次可用时,保存的消息会被推送。但是,苹果只会为同一个设备保留最近的一条消息。如果在设备持续无法联网的情况下,服务提供方再次推送消息,会导致上一条推送消息的丢失,而且不会告知。这对于普通消费型应用问题不大,但对于企业级应用则不然,特别是对于某些重要性很高,而且推送消息很频繁的移动应用而言,随意丢弃消息是不可接受的。   (2)不保证消息传递时效。APNS服务宣称会尽快传递消息,但不保证多长时间内可以传递到,不能要求限时到达。而且,它没有消息优先级的设置,所有的消息都按照同样的优先级传递,不能对消息区别对待。   (3)消息大小有限制。如果移动设备的操作系统不是最新的iOS 8,那么推送消息内容不能超过256字节,只能用来传递一些最简单的消息。企业级应用中,这么小的数据量几乎是无法使用的。如果将移动设备升级到iOS 8,最大推送字节数会增加到2000字节。很多情况下,这一数值也无法满足企业级移动应用的要求。   (4)发送频率受控。苹果官方对单位时间内允许推送的消息数没有限定,但在实际使用时发现,如果与推送服务器建立的网络连接数过多,或者推送消息的频率过于密集,都会导致苹果拒绝服务,无法推送。   (5)不支持消息回执。最终用户有没有收到消息?如果客户端收到了,具体是什么时间点收到的?这种需求对于企业应用很常见,但APNS并没有提供类似的消息回执机制。   (6)无法控制数据安全。虽然APNS提供了相应的数据传输安全机制,确保在传输过程中的安全,但数据毕竟是经过苹果的服务器传递,而且,如果设备不在线,消息还会在苹果的服务器上保存。这对于一些对数据敏感性有要求的组织或机构而言是不允许的。某些要求严格的企业,甚至会要求移动设备全部使用VPN专有网络,所有的互联网服务都不允许访问,这种情况TAPNS就更无法使用了。   2.2谷歌云推送(GcM,Google Cloud Messaging forAndroid)   与苹果类似,谷歌也为Android设备提供了一个公共的消息推送服务,其架构如图2所示。与APNS类似,第三方应用需要推送消息时,只需要连接到一个GCM服务器,调用消息推送服务,就可以将消息传递到指定的移动设备,并唤起相应的移动应用。
  谷歌云推送在功能上较APNS有不少增强,支持包括消息回执功能,send-to-sync消息机制等,其最大可推送的消息内容也较苹果的大,为4000字节。   但是,现实的情况是,由于网络原因,谷歌的推送服务在国内根本无法访问,无法访问谷歌的GCM服务器,谷歌的GCM服务器也无法与我们的移动手机建立推送连接。而且,消息推送需要手机与服务器两者的相互配合,手机端必须具备相应的GCM接收服务,才能接收到推送的消息,但由于Android手机厂商的分裂状态,几乎每个手机厂商都会用自己的推送服务替代原有的GCM接收服务,这就导致即使GcM月艮务器可以访问,手机端也无法接收到消息。除非能全部限定所有的移动设备为同一家供应商,否则也无法使用手机厂商提供的推送服务。而现实中,几乎不存在这种设备完全由同一个厂商供应的可能性。   需要说明的是,基于谷歌一贯的开放策略,GCM也是一个开放性的标准,任何人或企业都可以直接使用谷歌提供的推送云服务,也可以自行根据GCM服务端的标准规范实现私有的GCM推送服务。不过,GCM在消息通讯协议上只有HTTP和XMPP两种选择,这两种协议无论从传输效率,可靠性角度,还是从安全的角度看,都不是最适合移动应用的协议。   综上所述,消息推送作为一个新的技术话题,在协议规范和技术标准方面都还没有形成业界标准,苹果和谷歌作为业界领先的两大企业,虽然提供了针对各自平台的推送服务,但都存在不同程度的问题,特别是对于企业级高端用户而言。   构建消息推送服务是一个系统工程,需要进行完备的架构设计。这其中,推送协议的选择至关重要,不同的协议会直接影响推送的速度,服务质量和用户满意度。   3MQTT协议   消息队列遥测传输(MQTT,Message QueuingTelemetry Transport)协议是IBM公司提出的开放协议,最初的设想是应用于大量计算能力有限的传感器等微型设备,其工作的网络带宽低且不稳定,但又需要保证网络节点之间的可靠通讯。   该协议目前已经被结构化信息标准促进组织(OASIS)接受,并将其建议为物联网消息传递协议的首选标准。MQTT已经成为物联网领域的事实标准,IBM公司已经成功将其应用于智能实验室、远程医疗中心等项目,并推出了MessageSight等MQTT中间件产品,其它企业和机构也相继跟进,发布支持MOTT协议的开源/商业产品,或采用MQTT协议构建相关应用。伴随着物联网的迅猛发展,MQTT协议未来的发展不可限量。   由于物联网传感器等设备的计算能力和电量都非常有限,因此MQTT的设计理念从一开始就是简单,轻量,节省电力,这正好满足了移动应用的一个重要诉求。当前电池储能技术的发展远远不能满足智能手机的发展需要,使用智能手机用户最痛苦的事情就是手机耗电太快,手机的电量甚至不能支持完8小时的工作时间。但如果要保证消息及时到达,手机就必须时刻保持与服务器的连接,并定期与其通讯,检查是否有新消息。MQTT协议非常精简,额外的数据传输量非常小,可以在最大限度节省电力,同时也节省网络流量。这是选择MQTT构建消息推送服务的最大原因。   MOTT协议的消息头固定为2个字节,当前只使用了第一个字节,第二个字节保留。第一个字节共8个bit位,前4位为控制类型,可取值为16种,按照功能可以分为连接类,订阅类,保持活动类几种,后4位携带每种控制类型的特有信息如表1所示。   作为对比,让我们来看看最常见的HTTP协议的消息头,如图3所示为访问百度主页()时,HTTP请求所提交的消息头信息,其数据量超过300字节,是MQTT协议(2个字节)的150倍。而且,这只是一个比较小的HTTP消息头,如果用户多次访问同一网站,会有不断增长的Cookie信息,消息头的内容会更多。   为了实现及时推送,手机需要周期性给服务器发送请求(心跳),以保持与消息推送服务器的连接不中断。假设手机每30秒发送一次心跳,每天就需要发送2880次,如果采用MQTT协议,只需5k的通讯流量,而如果采用HTTP方式,则需要的流量为864k,其高下一目了然。而手机需要消耗的电力与需要传输的数据量直接相关。   除了短小精悍,节约带宽,节省电量消耗,MQTT协议还具有其它的特性,非常适合用于构建移动应用的消息推送服务。   (1)保证服务质量。MQTT提供三种消息传输的服务质量保障水平,用户可以根据实际需要进行选择:   QoS0:至多传递一次。消息有可能会丢失。这种服务质量下,消息传递的速度最快,但不能保证消息的可靠到达。通常适用于网络环境差,而且不在意单次数据丢失的情况,例如GPS数据的采集。   QoS1:至少传递一次。可以确保消息被可靠传递到目标,但可能会有消息被重复传递。这种服务质量权衡了传输效率和消息可靠性,最常被采用。   QoS2:确定只传递一次。消息不会被丢失,也不会被重复传递。这种服务质量被用来保证最高的消息传递服务质量。   (2)连接中断通知。与物联网类似,手机的网络质量远不能与连接网线的台式机相比,当我们发生位移时,或者进入电梯,地下室等区域时,手机经常会发生基站切换,网络信号消失,连接中断等情况。MQTT协议可以很好地适应这种不稳定的网络环境,并且保证数据的可靠传输。而且,当发生网络异常中断时,MQTT还支持遗嘱机制,将网络中断事件通知给指定的目标对象。   (3)信息广播机制。MQTT采用发布/订阅机制来传递信息,多个手机终端可以订阅同一个主题;服务端只需要针对主题发布信息,所有订阅者都可以收到,而无需对逐个手机发送,简单高效。例如,股票价格信息,不同的人可以订阅关注同一个股票的价格信息,当该股票的价格发生变化时,服务端只需发布一次最新价格,所有的订阅者都会收到同样消息。
  4其它问题   在采用MQTT协议构建移动应用的消息推送服务时,也应当了解MQTT的不足,并妥善处理如下问题。   4.1避免客户端越权订阅   MQTT采用发布/订阅模式处理消息传递,消息是针对主题传递,而不是目标客户端。客户端只要进行订阅,就可以收到消息。理论上,如果某个客户端订阅了根主题,就可以收到所有人的消息,这是不可接受的。   可以启用MQTT的用户认证机制,只有经过认证的用户才可以订阅主题,但这只能防止非认证用户的恶意订阅,对于认证通过的用户则不起作用。   彻底的解决方法需要在服务端进行控制,不允许用户订阅其没有权限的主题。另外,一些MQTT产品对此也有处理,例如,IBM的MessageSight产品就支持点对点和发布/订阅两种方式,而使用点对点方式时,任意订阅都不起作用。   4.2处理iOS后台服务运行   ios系统对于后台服务的长时间运行有很多限制,MQTT要求与服务端―直保持连接,在iOS系统下不容易做到。当移动APP在前台运行时,MQTT可以建立并保持与推送服务器的连接,但是,一旦移动APP被推入后台,所有的活动,包括连接都会被中断。   iOS允许某些应用在后台保持运行,但需要经过苹果的-审核,而且服务端还需要定期给移动设备发送数据以保持网络连接,相对而言较为繁琐。   另4中解决方式是将MQTT推送与APNS相结合,当MQTT连接被中断时,推送改为使用APNS通道。当有新消息需要推送时,推送服务器发送一个APNS的提示消息(没有具体消息内容),然后由APNS消息激活移动应用,唤起MQTT月艮务,再通过MQTT渠道具体的推送消息内容。这种方式只将APNS作为一个旁路提醒通道,不传递消息内容,保证了数据的安全性。   4.3可扩展的MQTT服务端   消息推送需要移动设备与推送服务器保持长连接,这与传统应用不同。传统的B/s应用是短连接模式,客户端向服务端发起请求,服务端处理完成后返回结果给客户端,然后释放连接。如果不考虑业务逻辑处理对服务器资源的使用,单个服务器可以轻松支持几十万,甚至上百万的用户访问。但是,如果拿一台普通的服务器当做消息推送服务器,单台服务器的连接能力大约在2万到10万之间,如果要保证稳定的服务能力,客户端的连接数通常不允许超过5万。IBM的MessageSight可以支持100万的客户端连接。但不论其数值多少,单台服务器的处理能力总有极限。   如果要推送的设备数量超过了单台的处理能力,就需要考虑服务端集群。MQTT在服务端的集群扩展方面没有规定,需要自行设计实现水平扩展架构。
转载请注明来源。原文地址:
【xzbu】郑重声明:本网站资源、信息来源于网络,完全免费共享,仅供学习和研究使用,版权和著作权归原作者所有,如有不愿意被转载的情况,请通知我们删除已转载的信息。
xzbu发布此信息目的在于传播更多信息,与本网站立场无关。xzbu不保证该信息(包括但不限于文字、数据及图表)准确性、真实性、完整性等。

我要回帖

更多关于 mqtt 离线消息推送 的文章

 

随机推荐