您的位置:首页 > 移动开发 > Android开发

smack 源码分析- PacketWriter (android上实现长连接)【2】

2013-04-12 14:38 405 查看
上一篇smack 源码分析一(android上实现长连接) 整体分析了smack长连接的流程, 本篇将详细介绍PacketWriter.

PacketWriter是在上篇在介绍initConnection()方法中创建的,那么详细看下PacketWriter的实现:

[java] view
plaincopy

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);

}

/**

* 向网络流写数据包

* @param thisThread

*/

private void writePackets(Thread thisThread) {

try {

// Open the stream.

openStream();

// Write out packets from the queue.

while (!done && (writerThread == thisThread)) {

Packet packet = nextPacket();

if (packet != null) {

synchronized (writer) {

writer.write(packet.toXML());

writer.flush();

// Keep track of the last time a stanza was sent to the

// server

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是如何发送心跳包的:

[java] view
plaincopy

/**

* A TimerTask that keeps connections to the server alive by sending a space

* character on an interval.

*/

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 {

// Sleep 15 seconds before sending first heartbeat. This will give time to

// properly finish TLS negotiation and then start sending heartbeats.

Thread.sleep(15000);

}

catch (InterruptedException ie) {

// Do nothing

}

while (!done && keepAliveThread == thread) {

synchronized (writer) {

// Send heartbeat if no packet has been sent to the server for a given time

if (System.currentTimeMillis() - lastActive >= delay) {

try {

writer.write(" ");

writer.flush();

}

catch (Exception e) {

// Do nothing

}

}

}

try {

// Sleep until we should write the next keep-alive.

Thread.sleep(delay);

}

catch (InterruptedException ie) {

// Do nothing

}

}

}

}

心跳发送类: KeepAliveTask 是一个自定义线程, 它定义了心跳发送的时间间隔, 在其run方法里面一个无限循环体每隔delay毫秒就向云端发发送一个空消息(当然, 如需要你可以根据项目需求自定义一个心跳包).
整个PacketWriter介绍基本到此结束, 在你应用登陆成功之后就可以开启KeepAliveTask 线程定时发送心跳包到服务器保持终端与服务器的长连接.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: