AndroidPN客户端分别启动了读和写线程之后,如果有某种写必须等待结果的又如何处理呢?比如客户端向服务端发个消息,要求等待服务端返回后再对本地逻辑做处理。想象一下客户端要求修改密码,PacketWriter把请求write出去后,成功或失败信息肯定是从PacketReader线程中获得,那么如何把二者关联起来呢,看看asmack的做法。
PacketCollector类
public class PacketCollector { private PacketFilter packetFilter; private ArrayBlockingQueue<Packet> resultQueue; private Connection connection; private boolean cancelled = false; /** * Creates a new packet collector. If the packet filter is <tt>null</tt>, then * all packets will match this collector. * * @param conection the connection the collector is tied to. * @param packetFilter determines which packets will be returned by this collector. */ protected PacketCollector(Connection conection, PacketFilter packetFilter) { this(conection, packetFilter, SmackConfiguration.getPacketCollectorSize()); } /** * Creates a new packet collector. If the packet filter is <tt>null</tt>, then * all packets will match this collector. * * @param conection the connection the collector is tied to. * @param packetFilter determines which packets will be returned by this collector. * @param maxSize the maximum number of packets that will be stored in the collector. */ protected PacketCollector(Connection conection, PacketFilter packetFilter, int maxSize) { this.connection = conection; this.packetFilter = packetFilter; this.resultQueue = new ArrayBlockingQueue<Packet>(maxSize); } /** * Explicitly cancels the packet collector so that no more results are * queued up. Once a packet collector has been cancelled, it cannot be * re-enabled. Instead, a new packet collector must be created. */ public void cancel() { // If the packet collector has already been cancelled, do nothing. if (!cancelled) { cancelled = true; connection.removePacketCollector(this); } } /** * Returns the packet filter associated with this packet collector. The packet * filter is used to determine what packets are queued as results. * * @return the packet filter. */ public PacketFilter getPacketFilter() { return packetFilter; } /** * Polls to see if a packet is currently available and returns it, or * immediately returns <tt>null</tt> if no packets are currently in the * result queue. * * @return the next packet result, or <tt>null</tt> if there are no more * results. */ public Packet pollResult() { return resultQueue.poll(); } /** * Returns the next available packet. The method call will block (not return) * until a packet is available. * * @return the next available packet. */ public Packet nextResult() { try { return resultQueue.take(); } catch (InterruptedException e) { throw new RuntimeException(e); } } /** * Returns the next available packet. The method call will block (not return) * until a packet is available or the <tt>timeout</tt> has elapased. If the * timeout elapses without a result, <tt>null</tt> will be returned. * * @param timeout the amount of time to wait for the next packet (in milleseconds). * @return the next available packet. */ public Packet nextResult(long timeout) { try { return resultQueue.poll(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new RuntimeException(e); } } /** * Processes a packet to see if it meets the criteria for this packet collector. * If so, the packet is added to the result queue. * * @param packet the packet to process. */ protected void processPacket(Packet packet) { if (packet == null) { return; } if (packetFilter == null || packetFilter.accept(packet)) { while (!resultQueue.offer(packet)) { // Since we know the queue is full, this poll should never actually block. resultQueue.poll(); } } } }
这个类相当赞,最喜欢这种简单的东西了,我觉得我可以照抄呵呵,基本上不需要看其它代码就能猜asmack是怎么干的了,看看流程
1.首先,如果有需要,比如要修改密码了,就将PacketCollect注册到connection上
/** * Creates a new packet collector for this connection. A packet filter determines * which packets will be accumulated by the collector. A PacketCollector is * more suitable to use than a {@link PacketListener} when you need to wait for * a specific result. * * @param packetFilter the packet filter to use. * @return a new packet collector. */ public PacketCollector createPacketCollector(PacketFilter packetFilter) { PacketCollector collector = new PacketCollector(this, packetFilter); // Add the collector to the list of active collectors. collectors.add(collector); return collector; }
PacketFilter是个过滤器,对于修改密码而言,我只对服务端返回的密码修改结果感兴趣,其它无视,那么它只将相关的接收到的packet放进PacketCollector的ArrayBlockingQueue<Packet>中。注意下processPacket这个方法,队列满了就开始丢弃之前的packet.
2.发起修改密码请求到服务端,其实就是通过PacketWriter线程write一个packet给服务器。
3.坐等服务端返回,可用nextResult()方法,是一直阻塞,还是阻塞一定时间,你自己来定,一般应该是阻塞几秒就差不多了。
4.最后无论有没服务端回应,cancel掉这个PacketCollector,即从connection中将之删除。
来看一段AccounterManager中源码:
public void createAccount(String username, String password, Map<String, String> attributes) throws XMPPException { if (!supportsAccountCreation()) { throw new XMPPException("Server does not support account creation."); } Registration reg = new Registration(); reg.setType(IQ.Type.SET); reg.setTo(connection.getServiceName()); attributes.put("username",username); attributes.put("password",password); reg.setAttributes(attributes); PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); PacketCollector collector = connection.createPacketCollector(filter); connection.sendPacket(reg); IQ result = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); // Stop queuing results collector.cancel(); if (result == null) { throw new XMPPException("No response from server."); } else if (result.getType() == IQ.Type.ERROR) { throw new XMPPException(result.getError()); } }
这个过程还是相当清楚的。
总结下,asmack写线程和读线程之间,通过分发指定消息类型到指定的同步队列,利用同步队列的阻塞,来实现发出消息和收到消息的关联。
相关推荐
2. **心跳机制**:为了保持连接状态并检测网络中断,客户端会定期发送心跳包给服务端。这有助于确认客户端在线并准备接收消息。 3. **消息处理**:客户端需要实现接收和解析服务端发送过来的JSON格式的推送消息。...
2. **客户端组件**: - **Service**:AndroidPN客户端通常包含一个后台Service,持续运行并监听服务器的推送消息。 - **BroadcastReceiver**:用于接收系统级别的广播,当设备接收到新的推送消息时触发。 - **...
Androidpn客户端 和服务端源码下载,实现了消息推送。具体使用方法可百度。
"AndroidPN 客户端和服务端"是一个完整的推送通知服务解决方案,主要针对Android平台。这个项目包括了客户端应用程序和服务器端的实现,旨在提供实时、可靠的信息推送功能,使得应用程序能够在用户不主动打开应用的...
接下来是客户端部分,`androidpn-client-0.5.0`包含了客户端的源代码。客户端的职责包括: 1. **注册**:客户端在启动时会连接到服务端,并注册其设备以便接收通知。这通常涉及到获取GCM或FCM的注册ID并将其发送到...
2. **AndroidPn客户端**:客户端是运行在Android设备上的应用程序,它的功能包括: - **连接建立**:通过TCP/IP或WebSocket等协议与服务端建立安全的连接。 - **身份认证**:向服务端提供身份凭证,以证明客户端...
"AndroidPN"是一个基于Android平台的推送通知服务(Push Notification)客户端和服务端的实现。它允许应用程序在后台运行,即使用户没有直接与应用交互,也能接收到服务器发送的消息。这个技术对于开发实时通信或者...
AndroidPN(Android Push Notification)是一种基于XMPP(Extensible Messaging and Presence Protocol)协议的开源消息推送客户端,主要用于Android平台。XMPP是一种开放标准的即时通讯协议,它允许应用程序通过...
AndroidPN(Android Push Notification)客户端是一款专门为Android操作系统设计的应用程序,用于实现远程服务器向设备推送通知的功能。在移动应用开发中,推送通知是一项至关重要的特性,它允许应用程序在后台状态...
2. 可扩展性:基于XMPP协议,AndroidPN客户端支持自定义扩展,可以适应各种复杂的应用场景。 3. 安全性:客户端和服务器之间的通信进行了加密,保证了数据的安全传输。 4. 稳定性:针对Android系统的特点进行优化,...
这个"基于androidpn设计的android客户端远程推送demo"应该包含以下部分: 1. **源代码**:Android应用的源代码,可能包括Activity、BroadcastReceiver、Service等关键组件。 2. **配置文件**:如GoogleService....
androidpn 的客户端和服务器端源码. 使用说明: 解压后得到两个压缩包: androidpn-client.zip和androidpn-server-0.5.0-bin.zip, 解压两个包,Eclipse导入client,配置好目标平台,打开raw/androidpn.properties...
Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件...
《AndroidPN客户端0.5.0:XMPP技术在手机消息推送中的应用》 AndroidPN客户端0.5.0是一款专为Android平台设计的消息推送服务,它基于XMPP(Extensible Messaging and Presence Protocol)协议,提供了开源的客户端...
"AndroidPN-client-0.5.0.zip" 是一个针对Android平台的Push Notification服务客户端的压缩包文件。Push Notification(简称PN)是一种允许服务器向移动设备推送消息的技术,无需应用程序处于活动状态。在这个版本...
AndroidPN客户端是安装在用户Android设备上的应用程序,它的主要任务是接收来自服务器端的消息并将其展示给用户。客户端通过注册一个唯一的设备ID到服务器,然后保持与服务器的持久连接,以便随时接收推送通知。这种...
本资源包提供了AndroidPN服务端和客户端的源码,以及相关的部署说明,便于开发者快速理解和实现推送通知功能。 一、AndroidPN服务端 AndroidPN服务端是基于Java语言开发的,它使用了Spring框架和Hibernate ORM来...
androidpn基于Xmpp的消息推送源码包含了完整的客户端和服务器端。androidpn客户端需要用到一个基于java的开源XMPP协议包asmack,这个包同样也是基于openfire下的另外一个开源项目smack,不过我们不需要自己编译,...
2. **客户端**:AndroidPN客户端是安装在Android设备上的应用程序,它负责注册到服务端,接收并处理来自服务端的推送消息。这里的"androidpn-client 0.5.01111"就是客户端的源码包,包含了实现消息推送所需的所有...