前段时间应一个项目需求: 要求给终端短信, 联系人信息做一个云存储云备份及云端远程控制终端并且云端能够推送消息到终端的需求. 这需要在终端与云端建立一个长连接以便云端消息能及时推送到终端. 所以项目中用到了smack框架. smack功能强大, 远不止本文所写的这点内容. 现在我只将对smack的理解以及项目中对smack的使用心得总结并记录下来, 一则给大家分享 , 二则也算是一个技术经验的累积. 但基于我混乱的表达能力和可能的理解上的偏差可能会有些错误. 欢迎各位大虾大牛拍砖.
项目中用到smack的长连接这块关键有以下这几个类: Connection , XMPPConnection , PakcetWriter , PacketReader. 如下图:
查看XMPPConnection源码:
protected void connectUsingConfiguration(ConnectionConfiguration config) throws XMPPException { String host = config.getHost(); int port = config.getPort(); try { if (this.socket == null || this.socket.isClosed()) { LogUtil.i(TAG, "this.socket == null || this.socket.isClosed()"); if (config.getSocketFactory() == null) { this.socket = new Socket(host, port); } else { this.socket = config.getSocketFactory().createSocket(host, port); } }
可以看到, connectUsingConfiguration(ConnectionConfiguration config) 是长连接入口, 传递config制定服务器ipAddress和port , 然后根据config创建一个socket对象. 紧接着调用initConnection()方法, 而在initConnection()中:
private void initConnection() throws XMPPException { usingCompression = false; // Set the reader and writer instance variables initReaderAndWriter(); try { // if (isFirstInitialization) { packetWriter = new PacketWriter(this); packetReader = new PacketReader(this); // If debugging is enabled, we should start the thread that will // listen for // all packets and then log them. if (config.isDebuggerEnabled()) { addPacketListener(debugger.getReaderListener(), null); if (debugger.getWriterListener() != null) { addPacketSendingListener(debugger.getWriterListener(), null); } } // } else { // packetWriter.init(); // packetReader.init(); // } // Start the packet writer. This will open a XMPP stream to the // server packetWriter.startup(); // Start the packet reader. The startup() method will block until we // get an opening stream packet back from server. packetReader.startup(); // Make note of the fact that we're now connected. connected = true;
以上执行顺序是
1. initReaderAndWriter()方法通过上面创建的socket实例化connection
的Writer和Reader.
2. 实例化PacketWriter和PacketReader对象.
PacketWriter就是向服务器发送数据发送心跳包一直保持与服务器的连接连. PacketReader则是不断的读取并且解析服务器推送的消息.
3. 分别调用packetWriter和packetReader的startup()方法.
至此整个连接过程就建立完成了.
长连接大致流程基本就这样, 也许还是一头雾水.
1.终端如何发生心跳包与服务器一直保持联系的呢.
2.服务器推送消息到终端, 终端是如何根据消息进行分发处理的呢.
请看: smack 源码分析- PacketReader (android上实现长连接) 和
smack 源码分析- PacketWriter (android上实现长连接) 两篇文章.