Android 心跳包心跳链接 如何实现android和服务器长链接呢?推送消息的原理

前言:如今的大多数移动端应用都有实时获得消息的能力,简单来讲,有发送消息的主动权和接受消息的被动权。例如:微信,QQ,天气预报等等,相信好处和用户体验相信你们都知道吧。java

 

提出问题:这种功能必须涉及client(客户端)和server(服务器),因此到底client如何和server实现实时链接通信?android

 

分析问题:这种功能实际上就是数据同步,同时要考虑手机自己、电量、网络流量等等限制因素,因此一般在移动端上有一下两个解决方案:
1.一种是定时去server查询数据,一般是使用HTTP协议来访问web服务器,称Polling(轮询);
2.还有一种是移动端和服务器创建长链接,使用XMPP长链接,称Push(推送)。(按照本人理解:客户端的实现时:web

1 while(true) {
2 
3  request(timeout);
4 
5  request(timeout);
6 
7 }

 

客户端发出一个“长”请求,若是服务器发送消息或者时间out了,客户端就断开这个请求,再创建一个长请求服务器



从耗费的电量、流量和数据延迟性各方面来讲,Push有明显的优点。可是使用Push的缺点是:
对于客户端:实现和维护相对成本高,在移动无线网络下维护长链接,相对有一些技术上的开发难度。
对于服务器:如何实现多核并发,cpu做业调度,数量庞大的长链接并发维护等技术,仍存在开发难点。

在讲述Push方案的原理前,咱们先了解一下移动无线网络的特色。
移动无线网络的特色:
由于 IP v4 的 IP 量有限,运营商分配给手机终端的 IP 是运营商内网的 IP,手机要链接 Internet,就须要经过运营商的网关作一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关须要维护一个外网 IP、端口到内网 IP、端口的对应关系,以确保内网的手机能够跟 Internet 的服务器通信微信

 

原理图以下:网络

 

GGSN(Gateway GPRS Support Node 网关GPRS支持结点)模块就实现了NAT功能。
由于大部分移动无线网络运营商都是为了减小网关的NAT映射表的负荷,因此若是发现链路中有一段时间没有数据通信时,会删除其对应表,形成链路中断。(关于NAT的做用及其原理能够查看个人另外一篇博文:关于使用UDP(TCP)跨局域网,NAT穿透的心得)
 
Push在Android平台上长链接的实现:
既然咱们知道咱们移动端要和Internet进行通讯,必须经过运营商的网关,因此,为了避免让NAT映射表失效,咱们须要定时向Internet发送数据,由于只是为了避免然NAT映射表失效,因此只需发送长度为0的数据便可。

这时候就要用到定时器,在android系统上,定时器一般有一下两种:
1.java.util.Timer
2.android.app.AlarmManager

分析:
Timer:能够按照计划或者时间周期来执行相关的任务。可是Timer须要用WakeLock来让CPU保持唤醒状态,才能保证任务的执行,这样子会消耗大量流量;当CPU处于休眠的时候,就不能唤醒执行任务,因此应用于移动端明显是不合适。

AlarmManager:AlarmManager类是属于android系统封装好来管理RTC模块的管理类。这里就涉及到RTC模块,要更好地了解二者的区别,就要明白二者真正的区别。
RTC(Real- Time Clock)实时闹钟在一个嵌入式系统中,一般采用RTC 来提供可靠的系统时间,包括时分秒和年月日等;并且要求在系统处于关机状态下它也可以正常工做(一般采用后备电池供电),它的外围也不须要太多的辅助电路,典型的就是只须要一个高精度的32.768KHz 晶体和电阻电容等。(若是对这方面感兴趣,能够本身查阅相关资料,这里就说个大概)
好了,回来正题。因此,AlarmManager又称全局定时闹钟。这意味着,当我用使用AlarmManager来定时执行任务,CPU能够正常地休眠,只有在执行任务是,才唤醒CPU,这个过程是很短期的。并发


下面简单来讲明其使用:app


1.相似于Timer功能:
//得到闹钟管理器
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
//设置任务执行计划
am.setRepeating(AlarmManager.ELAPSED_REALTIME, firstTime, 5*1000, sender);//从firstTime才开始执行,每隔5秒再执行

2.实现全局定时功能:
//得到闹钟管理器
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
//设置任务执行计划
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, 5*1000, sender);//从firstTime才开始执行,每隔5秒再执行

总结:在android客户端使用Push推送时,应该使用AlarmManager来实现心跳功能,使其真正实现长链接。


在服务器端的实现:
在服务器端,可使用不少语言来实现,如C/C++,java,Erlang等等,如咱们国内比较好的极光推送(C开发),openfire(java开发)等等。
最近我看了极光推送的介绍和原理,下面我就说说他们是遇到什么难题,而后使用什么技术或者方案来解决呢。

当有大量的手机终端须要与服务器维持长链接时,对服务器的设计会是一个很大的挑战。


假设一台服务器维护10万个长链接,当有1000万用户量时,须要有多达100台的服务器来维护这些用户的长链接,这里还不算用于作备份的服务器,这将会是一个巨大的成本问题。那就须要咱们尽量提升单台服务器接入用户的量,也就是业界已经讨论好久了的 C10K 问题。
C2000K


针对这个问题,他们专门成立了一个项目,命名为C2000K,顾名思义,他们的目标是单机维持200万个长链接。最终他们采用了多消息循环、异步非阻塞的模型,在一台双核、24G内存的服务器上,实现峰值维持超过300万个长链接。




最后总结:
        由于我最近用java在作一个PC、服务器、android的即时通信系统(说白了就是模仿QQ,后面但愿有不一样的功能)。个人原则是用别人的原理,本身来实现,这样才更好深刻了解一些框架。因此,估计难点是在通信开发和服务器上的开发,必须深入了解多消息循环、异步非阻塞的模型。以后我会发表关于这方面的实现。
       在如今的android平台上,已经不是android单机的世界了(我不是说作单机游戏没有前途)。如今都是依靠发展蓬勃的互联网来支撑整个IT体系,因此,要成为一个android应用开发高手,必须朝着android、硬件、云服务这一体系来发展。
参考文档:http://blog.csdn.net/sunmenggmail/article/details/12008075
框架

相关文章
相关标签/搜索