在 Connection 抽象類中,有一個屬性 collectors ,類型是 Collection<PacketCollector> 。 collectors 是一個由 PacketCollector組成的集合。
一、簡介
PacketCollector 是一個Packet數據蒐集器,根據設置的filter來接收packet數據。
如果filter爲空,則接收全部的packet數據。
二、工作原理
怎麼接收呢?
PacketCollector中有一個 ArrayBlockingQueue 類型的結果隊列 resultQueue,
所有的滿足條件的packet都進入隊列。
進隊列的規則是:從隊列尾部進,從隊列頭部出。隊列滿了,先進的 packet 就從隊列頭部溢出,讓後來的 packet 進入隊列。
這個規則就是有 processPacket(Packet packet) 來執行的,此方法接收新的 packet,然後執行上述進隊列的規則。
三、用途
那麼,這個 PacketCollector 有什麼用呢?
他是爲了專門滿足某些條件的 packet,比如:在一個修改密碼的操作之後,加上一個packetColletor 專門蒐集能夠響應這個操作的返回結果。
如果這個 packetCollector 裏面的 packet 一個也沒有,也就是隊列爲空,則沒有收到服務器端的響應。
如果有packet ,就可以獲得這個packet 讀取返回的結果。
四、用法舉例
1、創建一個filter
PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()),
new PacketTypeFilter(IQ.class));
滿足這個filter的所有 packet 都會進入 packetCollector 的隊列中。
2、用這個filter 創建一個 packetCollector
PacketCollector collector = connection.createPacketCollector(filter);
3、發送數據到服務器端
connection.sendPacket(reg);
4、接收響應
IQ result = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
5、結束蒐集
collector.cancel();
五、隊列的創建和操作
1、根據filter 創建一個 PacketCollector 並加入集合中
protected final Collection<PacketCollector> collectors = new ConcurrentLinkedQueue<PacketCollector>();
public PacketCollector createPacketCollector(PacketFilter packetFilter) {
PacketCollector collector = new PacketCollector(this, packetFilter);
collectors.add(collector);
return collector;
}
所以,每個connect 可以增加任意多個 packetCollector 。
在什麼時候加,在調用 connect.setPacket(packet)之前加,參見用法舉例的步驟。
2、獲取隊列中的數據
collector.nextResult()獲取結果,這個方法會等待隊列,直到返回結果爲止。得到的結果會彈出隊列,下一個結果成爲隊列的頂端元素。
還有一個方法:
collector.pollResult() 也是獲取結果,如果有就返回結果,沒有就返回null,不會鎖定隊列。
3、結束蒐集
collector.cancel()
六、蒐集工作的入口
之前在 PacketReader裏面,觸發Listener 前面。
- private void processPacket(Packet packet) {
- if (packet == null) {
- return;
- }
- // Loop through all collectors and notify the appropriate ones.
- for (PacketCollector collector : connection.getPacketCollectors()) {
- collector.processPacket(packet);
- }
- // Deliver the incoming packet to listeners.
- listenerExecutor.submit(new ListenerNotification(packet));
- }
七、補充
PacketCollector中隊列的大小在配置文件中設置。
配置文件 META-INF/smack-config.xml
對應的設置 <packetCollectorSize>10000</packetCollectorSize>
默認的是 10000
轉:http://blog.csdn.net/teamlet/article/details/25834573