彭 飞
(安徽信息工程学院计算机与软件工程学院,安徽 芜湖241000)
国内软件开发和服务型企业,都在尝试和提供消息推送服务.但是,对于专门从事软件开发的企业来说,掌握一个比较完整和合理的基于安卓原生框架的消息推送系统的设计原理,意义之重大不言而喻.可以在这个实现的基础之上,根据自身业务的需求,只要做与业务相关的部分,不再需要重复去设计底层功能.这样就简化了对设计的要求,同时,也对开发人员的能力要求方面有所降低.开发人员只是业务方面的行家,只要关注与自己业务相关的开发,努力把业务做到极致,把用户体验做到更加丰富多彩.对于底层、协议等这些比较晦涩、难懂的技术实现不需要关注.
XMPP[1]:中文意思是扩展消息出席协议.设计的目的是使用相对较小的结构化数据(称为“XML节”) 片段在网络完成上任何两个(或更多)实体之间的数据交换.典型的应用场景是分布式客户机-服务器体系结构,一个客户端需要连接到服务器才能与其他实体(或与其他某个服务器)交换XML节.
两个实体之间交换信息大体需要经历下面的过程.
(1)设置IP地址和需要连接到端口号,基于全域名解析;
(2)打开TCP(Transmission Control Protocol)连接;
(3)在TCP上打开XML流;
(4)协商TLS(Transport Layer Security)通道加密;
(5)使用SASL(Simple Authentication and Security Layer)机制验证身份;
(6)绑定资源流;
(7)通过网络与其他节点交换XML数据节;
(8)关闭 XML 流;
(9)关闭TCP 连接.
XMPP协议的网络应用通常被实现成基于分布式的客户端-服务器网络架构模型,实体之间采用TCP连接,并且每个客户端只能够与特定的服务器连接,要想实现端对端的连接,则中间必须经过一个或多个服务器的转发[2].所以,在基于XMPP 协议的通信链路中,根据扮演的角色来细分的话,整个通讯的结构可以划分成四大组件.
服务器:主要的功能是用来接收、转发或处理传输数据,不同的实体在服务器上都有一个唯一的标识,便于服务器来区分.服务器也扮演数据存储和管理客户端的功能,能够根据业务的需要实现功能定制和扩展.
客户端:信息传递的发起者,数据的传递必须通过服务器的转发才能到达其他服务器、客户端.每个客户端必须有明确的唯一的标识符,同时客户端必须完全支持TCP套接字(Socket),能够理解XML信息流的数据类型和正确解析XML数据.
网关:主要的功能是连接异构系统,实现互相通信,目的是实现不同协议之间的转换,起到一个协议信息转换的作用.
网络:是实现不同实体之间互联互通的通讯连接和信息传输的物理载体.
支持XMPP协议网络拓扑结构如图1所示.
图1 网络拓扑结构
XMPP地址格式和我们经常使用的电子邮件类似,使用全局唯一地址来标识XMPP的实体,利用域名系统在网络上转发和传递消息.XMPP协议规范中明确规定,所有实体都是可寻址的,不光是特别的客户端和服务器,而且提供附加服务的服务器都能被其他客户端和服务器访问.XMPP服务器地址类似“网络域名”形式,比如xm.mydomain.com,而注册在该服务器上账户地址形式mars@xm.mydomain.com,服务器设备或资源形式是mars@ xm.mydomain.com / balcon.XMPP出身Jabber,所以其地址被称为Jabber Id.所以,一个JID的信息是由实体名称、路由服务器和资源三部分组成[3].
消息推送的主要功能是向安卓手机客户端推送文本消息,底层的通讯协议使用XMPP协议,要实现这个功能,需要服务器端的支持.
服务器端需支持以下功能:
(1)能够完成安卓客户端的注册、连接和登录常用的功能.新的客户端第一次连接到服务器时,服务器获取客户端的信息并把信息写入后台的数据库.
(2)服务器一直监听客户端状态的变化(离线或在线),一旦客户端离线或在线,自动更新记录在数据库表中的客户端的状态,便于管理员随时通过管理页面查看当前在线用户的详细信息.
(3)服务端以管理员控制台的方式提供输入文本信息界面,输入需要推送的信息之后,能够把该条信息主动向安卓手机客户端推送.推送形式目前分为向指定的用户推送与向系统数据库中所有用户推送这两种形式.
安卓客户端需支持以下功能:
(1)App部署成功,打开消息推送功能,自动连接到指定的服务器完成新用户注册功能.注册的信息写入到手机中配置信息中,已经在服务器完成过注册之后,直接使用保存的注册信息登录.
(2)客户端提供心跳机制,定时向服务器发送连接来维护自己与与服务器的连接.
(3)安卓客户端属于移动设备,有可能使用WIFI接入,一旦离开WIFI的覆盖区域,自动向服务器发送连接断开的请求,当再次进入覆盖区域,具有断线重连的功能.
要实现上面定义的业务功能,需要从下面几个方面来思考:
(1)一个安卓客户端和服务器的通讯过程可以简化为一对一模型,通讯的过程是建立连接、传递数据和关闭连接.只不过,要使用XMPP协议的两个互相通讯的实体之间,传递的是XML数据流.Java语言提供的网络API很容易实现基于Socket的通讯网络.
(2)如果涉及到多个安卓客户端,那么通讯模型变成了一对多,服务器就需要维护连接列表来存放和处理每一个客户端数据.
(3)XML的消息流到达安卓客户端,需要被解析并以文本的形式展示,服务端的数据何时到达具有不确定性,所以,需要使用侦听机制来异步处理消息,Android提供的APIs已经能够满足这个功能.服务器如果向在线的安卓客户端发送一条信息,只需要遍历连接列表,使用Socket发送一段XML流即可.
通过上面的思考和分析,消息推送的底层通讯的本质是Java语言的Socket网络通讯,通过Socket建立的管道流中传输的是XML数据,这些数据是按照XMPP协议规范构造的,服务器和安卓客户端必须能够理解这些XML数据.所以,消息推送需要设计的基础类库必须要能实现下面的要求.
(1)附加在Socket通讯之上的应用必须要提供对Socket通讯的封装,提供性能优良的多客户端连接处理.
(2)需要设计一系列的类来抽象服务器和安卓客户端的连接、客户端会话以及对连接的处理.
(3)需要设计XML数据流的解析器,提供对XML到应用层数据解析工作,同时,基于XMPP通讯所需要的格式化XML数据构造器,完成应用层数据到XML的解析.
(4)消息接收和处理的时机具有不确定性,需要设计一系列的监听器来监听连接状态的变化,进而触发一系列事件.
消息推送暂时只支持向在线的安卓客户端推送文本消息.服务端需要完成的工作分成二块,第一块是在某个端口上监听安卓客户端套接字连接,连接一旦建立,安卓客户端需要使用长连接的方式主动和服务器保持连接,处理来自服务器的不同类型的消息.第二块是作为Web应用服务器,在80端口监听PC客户端浏览器的HTTP页面请求,管理员使用浏览器在远程呼出管理界面,实现对安卓客户端的管理和文本消息的推送.服务器能够响应浏览器的URL请求,调用部署在服务器上与URL请求一一对应的服务组件来处理请求,最后生成响应,呈现处理结果给客户端.
XMPP服务模块可以实现成一个独立的服务器,HTTP服务模块也是一个独立的应用服务器,两个服务模块局部数据是共享的.所以,系统结构设计可以用图2来表示.
XMPP服务模块设计重点在于,Android客户端和服务端的数据传输过程细节仍需要一系列结构的设计,包括连接的管理、认证管理以及出席状态的管理等等.XMPP服务模块是可以独立运行的服务,不依赖于HTTP服务,当服务启动之后,会有一系列的实例对象被生成,常驻在服务器的内存中.一种最佳的实践是使用容器来管理这些实例化的对象,Spring IOC在实例对象管理方法做的比较好,所以,XMPP服务模块在设计的时候,考虑使用IOC容器.
服务端的HTTP服务是典型的B/S结构的Web应用,已经有很多的成熟的框架供使用,目前比较流行的是SSH方案.
图2 推送系统结构设计
本文使用XMPP协议作为底层的通讯协议,对协议的内容、通讯规程和语法规则做了做深入的剖析,在此基础之上,对Android消息推送进行了需求分析,然后对支持该协议的客户端和服务端进行了概要设计和系统结构设计,有利于其他项目集成并实现消息推送功能.