http://blog.csdn.net/wqhjfree/article/details/7194416
上一篇smack 源码分析一(android上实现长连接) 整体分析了smack长连接的流程, 本篇将详细介绍PacketWriter.
PacketWriter是在上篇在介绍initConnection()方法中创建的,那么详细看下PacketWriter的实现:
- protected PacketWriter(XMPPConnection connection) {
- this.queue = new ArrayBlockingQueue<Packet>(500, true);
- this.connection = connection;
- init();
- }
-
-
-
-
- protected void init() {
- this.writer = connection.writer;
- done = false;
- lastActive = System.currentTimeMillis();
-
-
- writerThread = new Thread() {
- public void run() {
- writePackets(this);
- }
- };
-
- writerThread.setName("Smack Packet Writer (" + connection.connectionCounterValue + ")");
- writerThread.setDaemon(true);
-
- }
-
-
-
-
-
-
-
- private void writePackets(Thread thisThread) {
- try {
-
- openStream();
-
- while (!done && (writerThread == thisThread)) {
- Packet packet = nextPacket();
- if (packet != null) {
- synchronized (writer) {
- writer.write(packet.toXML());
- writer.flush();
-
-
- lastActive = System.currentTimeMillis();
- }
- }
- }
-
- synchronized (writer) {
- while (!queue.isEmpty()) {
- Packet packet = queue.remove();
- writer.write(packet.toXML());
- }
- writer.flush();
- }
-
- queue.clear();
- writer.write("</stream:stream>");
- writer.flush();
-
- } catch (IOException ioe) {
- if (!done) {
- done = true;
- connection.packetReader.notifyConnectionError(ioe);
- }
- } finally {
- try {
- if (writer != null) {
- writer.close();
- }
- } catch (Exception e) {
- }
- }
- }
在PacketWriter构造方法中传递参数XMPPConnection作为PacketWriter成员变量, 然后调用init()方法 ,而在init()方法中, 开辟一个线程专门用于向服务器写数据. writerPackets()里面是一个无限循环体, 不断的从消息队列queue读取pakcet消息读取完之后调用wirter.flush()方法, 将消息发送的服务器. 这个过程就完成了终端完服务器发送消息的过程.
接下来是, 终端如何与云端保持连接呢, 那肯定是发送心跳包咯. 我们来看下PacketWriter是如何发送心跳包的:
-
-
-
-
- private class KeepAliveTask implements Runnable {
-
- private int delay;
- private Thread thread;
-
- public KeepAliveTask(int delay) {
- this.delay = delay;
- }
-
- protected void setThread(Thread thread) {
- this.thread = thread;
- }
-
- public void run() {
- try {
-
-
- Thread.sleep(15000);
- }
- catch (InterruptedException ie) {
-
- }
- while (!done && keepAliveThread == thread) {
- synchronized (writer) {
-
- if (System.currentTimeMillis() - lastActive >= delay) {
- try {
- writer.write(" ");
- writer.flush();
- }
- catch (Exception e) {
-
- }
- }
- }
- try {
-
- Thread.sleep(delay);
- }
- catch (InterruptedException ie) {
-
- }
- }
- }
- }
心跳发送类: KeepAliveTask 是一个自定义线程, 它定义了心跳发送的时间间隔, 在其run方法里面一个无限循环体每隔delay毫秒就向云端发发送一个空消息(当然, 如需要你可以根据项目需求自定义一个心跳包). 整个PacketWriter介绍基本到此结束, 在你应用登陆成功之后就可以开启KeepAliveTask 线程定时发送心跳包到服务器保持终端与服务器的长连接.