PacketReader 如何实现smack数据监听机制和packet分发机制

17 篇文章 0 订阅
15 篇文章 3 订阅


前面说过, PacketReader 在构造函数中传递 XmppConnection的实例,并赋给自己的成员变量 connect;

又启动了一个  readerThread 线程,在 parsePackets() 方法中处理connect的输入数据流 (也就是socket的数据输入流)。


这时读入的数据是xml格式的(格式说明参见 Xmpp协议),

 parsePackets()方法负责将xml数据转换为java对象,

转换为java对象后,parsePackets() 调用  processPacket()方法处理传入的Java对象。


processPacket()方法将传入的Java对象传递个另一个线程由另一线程来处理。


线程切换的语句:


listenerExecutor.submit(new ListenerNotification(packet));



listenerExecutor是单线程执行线程池

ExecutorService listenerExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {


public Thread newThread(Runnable runnable) {

Thread thread = new Thread(runnable, "Smack Listener Processor (" + connection.connectionCounterValue + ")");

thread.setDaemon(true);

return thread;

}

});


执行的是线程是:

new ListenerNotification(packet);


所以,只要有数据从服务器端发送过来,经过转换后的java对象以packet的形式提交到线程池中,由 ListenerNotification 处理。

这有点类似触发器。


执行的是什么呢?


 
		public void run() {
			for (ListenerWrapper listenerWrapper : connection.recvListeners.values()) {
				try {
					listenerWrapper.notifyListener(packet);
				} catch (Exception e) {
					System.err.println("Exception in packet listener: " + e);
					e.printStackTrace();
				}
			}
		}
 
 

只要有数据从服务器端传过来,转换后的packet对象要全部传递给 connect.recvListener 中的所有listenerWrapper处理。

而 connect.recvListener 中的值是通过 connect.addPacketListener() 方法添加的。


数据是从connect里来,处理还是由connect中的监听器处理,PacketReader 完成了数据流的转换和触发机制。


PacketReader 提供了触发机制和数据转换,除了数据转换需要处理数据外,触发机制并不涉及到任何的数据。

数据转换完毕之后,到底任何处理的呢?

在 ListenerWrapper 中!


触发的过程是读取 connection.recvListeners.values() 然后遍历执行其中的 ListenerWrapper 实例的notifyListener()方法。

connection.recvListeners.values()是通过 connect.addPacketListener() 添加数据的,


 
    public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter) {
        if (packetListener == null) {
            throw new NullPointerException("Packet listener is null.");
        }
        ListenerWrapper wrapper = new ListenerWrapper(packetListener, packetFilter);
        recvListeners.put(packetListener, wrapper);
    }
 

触发机制是通过传递 packet 给通过   addPacketListener()加入到列表中的所有(可以有多个) listenter .


遍历调用的方法:

 
 public void notifyListener(Packet packet) {
            if (packetFilter == null || packetFilter.accept(packet)) {
                packetListener.processPacket(packet);
            }
        }
 


触发机制是通过传递 packet 给  connection.recvListeners 列表中的所有 listenter 和 filter,

按先后顺序调用 filter.accept() 和 processPacket() 方法 .



 connection.recvListeners 是通过 addPacketListener()加入Listener和filter的。

只要通过addPacketListener()加入我们的listener和filter,就能够处理 packet 数据,实现自己的业务逻辑!


数据分发机制:

所有的 packet 被分发到每个listener中,并且各个listener互不影响。



所有的listenser 都实现了 PacketListener 接口,这个接口只有一个方法: 


public void processPacket(Packet packet);


通过查找继承这个接口的子类,可以看到 n多对packet 处理的方法,非常值得学习。

下面是一些子类,更多的是匿名类。


//处理 Message 
 
       PacketFilter typeFilter = new PacketTypeFilter(Message.class);

        connection.addPacketListener(new PacketListener() {
            public void processPacket(Packet packet) {
                handlePacket(packet);
            }
        }, typeFilter);
    }

 

//处理文件上传的 
		connection.addPacketListener(new PacketListener() {
			public void processPacket(Packet packet) {
				fireNewRequest((StreamInitiation) packet);
			}
		}, new AndFilter(new PacketTypeFilter(StreamInitiation.class),
				new IQTypeFilter(IQ.Type.SET)));
	}
  

//处理多人聊天的

......


补充:


举个接受Message消息的例子:


//创建一个Message typeFilter 
PacketFilter messageFilter = new PacketTypeFilter(Message.class);

//创建一个message listener
PacketListener messageListener = new PacketListener() {
public void processPacket(Packet packet) {
System.out.println("*** handle message packet ");
}
};
//加入列表
connection.addPacketListener(messageListener, messageFilter);
 
现在运行起来就可以在messageListener里处理Message的业务逻辑了。



总结:


只要继承 PacketListener接口,实现自己的 pakcetListener,并通过connect.addListener()加入监听队列,

这个packetListener就可以在processPacket方法中得到packet ,进行自己的逻辑处理。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值