smack类库详细介绍


Smack 类库详细介绍 Smack 是一个为使用 XMPP 服务器聊天和发送即时消息交流而提供的库。 Smack 的主要优势: 使用简单且拥有强大的 API。向用户发送一条文本消息只需用一下三行代码即可完成 XMPPConnection connection = new XMPPConnection("jabber.org"); connection.login("mtucker", "password"); connection.createChat("jsmith@jivesoftware.com").sendMessage("Howdy!"); 不像其它库那样,强制你在信息报级(packet level)编码。Smack 提供智能的、更高级别的结构,例 如:Chat 和 GroupChat 类,这写能让你的程序效率更高。 你不需要熟悉 XMPP XML 格式,甚至不熟 XML。 提供简单的机器到机器的通讯。Smack 允许你对每一条消息设置任何数字的属性,包括 Java 对象的属性。 Apache 许可的开放源码,你可将其用于商业的和非商业的应用。 关于 XMPP XMPP (eXtensible Messaging and Presence Protocol)是一个开放的, 如何使用本文档 本文档假定你已经熟悉 XMPP 即时消息的主要特征。我们推荐你在阅读该文档时打开 Javadoc API 作为 参考。 开始 Smack 本文档将向你介绍 Smack API,并大概介绍几个重要的类和概念。 必备的条件 你只需要有 JDK 1.2 或之后的版本 1 和已经内嵌在 smack.jar 文件中的 XML 分析器,不需要第三部分库。 1JDK 1.2 and 1.3 的用户若想使用 SSL 连接必须在他的类路径下有 JSSE 库。 建立一个连接 XMPPConnection 类是为 XMPP 服务器建立连接的类。若要创建 SSL 连接,需使用 SSLXMPPConnection 类,以下是创建连接的例子。 // Create a connection to the jabber.org server. XMPPConnection conn1 = new XMPPConnection("jabber.org"); // Create a connection to the jabber.org server on a specific port. XMPPConnection conn2 = new XMPPConnection("jabber.org", 5222); // Create an SSL connection to jabber.org. XMPPConnection connection = new SSLXMPPConnection("jabber.org"); 如果创建了一个连接,你应该使用 XMPPConnection.login(String username, String password)方法 (参数为用户名和密码)进行登陆。一旦登陆成功,你就可以通过创建一个新的 Chat 或 GroupChat 对 象与其它用户聊天。 使用花名册(Working with the Roster) 花名册让你很清楚的知道其它可用的用户。用户可以被分成像“朋友”、“合作者”这样的组,从 而知道其它的用户在线还是离线。 可以使用 XMPPConnection.getRoster()方法检索花名册。你可以用花名册(roster)类查找花名册 的所有条目,它们所属的组以及每个条目当前呈现的状态。 读、写信息包(Reading and Writing Packets) 从客户端发送到 XMPP 的每一条消息称为一个信息包,并作为 XML 发送。The org.jivesoftware.smack.packet 包含封装了三个 XMPP 允许的、不同的基本包类型(message, presence, and IQ)的类。像 Chat 和 GroupChat 这样的类提供更高级别的结构,它可以自动的创建和发 送信息包,当然你也可以直接创建和发送信息包。以下代码是一个将你的当前状态改为“隐身“,从而 不被别人看到的例子: // Create a new presence. Pass in false to indicate we’re unavailable. Presence presence = new Presence(Presence.Type.UNAVAILABLE); presence.setStatus("Gone fishing"); // Send the packet (assume we have a XMPPConnection instance called "con"). con.sendPacket(presence); Smack 提供以下两种方法阅读收到的信息包:PacketListener 和 PacketCollector。它们都使用 PacketFilter 的实例来决定应该处理哪个信息包。信息包监听器(packet listener)用于事件类型的设计, 而信息包收集器(packet collector)有一个信息包的结果队列,你可以对其实施 polling 和 blocking 操 作。所以,信息包监听器在你收到任何一个信息包,且你想对其进行操作时是有用的,而信息包收集器 在你想等待某个特殊的信息包时是有用的。信息包收集器和监听器可以通过 XMPPConnection 的实例来 创建。 Messaging Basics Messaging using Chat and GroupChat 互相发送消息是即时通讯的核心,以下是两个在收发消息是用的类: org.jivesoftware.smack.Chat – 用于两个人之间发送消息 org.jivesoftware.smack.GroupChat –用于加入聊天室,很多人之间相互发送消息。 Chat 和 GroupChat 类都用 org.jivesoftware.smack.packet .Message 信息包类发送消息。在某些情况 下,也许你希望绕过更高级别的 Chat 和 GroupChat 类直接发送和接受消息。 聊天(Chat) 聊天时在两个用户间创建了一个新的线程(使用一个线程 ID)。以下程序片示例了如何如何与一个用户 进行开始聊天并发送一段文本消息: // Assume we’ve created an XMPPConnection name "connection". Chat newChat = connection.createChat("jsmith@jivesoftware.com"); newChat.sendMessage("Howdy!"); Chat.sendMessage(String)方法可以很方便的创建一个消息对象,方法体使用字符串类型的参数,然后 发送消息。如果想在发送消息前对消息设置额外的只,可以使用 Chat.createMessage() and Chat.send Message(Message)方法,如下例所示: // Assume we’ve created an XMPPConnection name "co nnection". Chat newChat = connection.createChat("jsmith@jivesoftware.com"); Message newMessage = newChat.createMessage(); newMessage.setBody("Howdy!"); message.setProperty("favoriteColor", "red"); newChat.sendMessage(newMessage); 使用 Chat 对象可以轻松的收听其它聊天者的回复。以下程序片是 parrot-bot,它映射会其它用户类型的所有事情: // As sume we’ve created an XMPPConnection name "connection". Chat newChat = connection.createChat("jsmith@jivesoftware.com"); newMessage.setBody("Hi, I’m an annoying parrot-bot! Type something back to me."); while (true) { // Wait for the next message the user types to us. Message message = newChat.nextMessage(); // Send back the same text the other user sent us. newChat.sendMessage(message.getBody()); } 以上代码使用 Chat.nextMessage()方法获得下一条消息,它必需一直等待直到收到下一条消息。也有其它的方法可以等 待特定的时间来接受下一条消息,或者你也可以增加一个监听器,它可以在每次收到消息时通知你。 群聊(GroupChat) 群聊在通过一个服务器连接到聊天室,你可以向一组人发送消息或接收他们的消息。在你能接收和发送消息前,你必须使 用一个昵称登陆到聊天室。以下程序段可以连接到一个聊天室并发送消息: // Assume we’ve created an XMPPConnection name "connection". GroupChat newGroupChat = connection.createGroupChat("test@jivesoftware.com"); // Join the group chat using the nickname "jsmith". newGroupChat.join("jsmith"); // Send a message to all the other people in the chat room. newGroupChat.sendMessage("Howdy!"); ,群聊时收发消息和私聊时工作原理大体一致。同样,也有方法可以获得聊天室里其它用户的列表。 Roster and Presence 花名册让你很清楚的知道其它可用的用户。用户可以被分成像“朋友”、“合作者”这样的组。其它的即使通讯系统将花 名册作为好友列表、联系列表等。 当你成功登陆服务器后,可以使用 XMPPConnection.getRoster()获得 Roster 类的实例。 花名册条目(Roster Entries) 花名册里的每一个用户都以一条花名册条目的形式呈现,包括以下几部分: 一个 XMPP 地址(例如:jsmith@example.com). 分配给你的用户名 (例如: "Joe"). 该条目在花名册中所属组的列表。如果该条目不属于任何一个组,将被称为“尚未分类的条目。 以下程序段可以打印出花名册中的所有条目: Roster roster = con.getRoster(); for (Iterator i=roster.getEntries(); i.hasNext(); ) { System.out.println(i.next()); } 也有获得个人条目、尚未分类条目的列表、一个或者所有组的方法。 呈现(Presence) 花名册中的每一个条目都有相关的呈现方式。Roster.getPresence(String user)方法将通过用户的状态或当用户不在线或 不同意将其在线状态显示出来时使用空对象(null)返回一个 Presence 对象。 注意:一般情况下,用户是否同意显示其状态依赖于用户所在的花名册,但这不是在所有情况下都成立的。 用户也有一个在线或离线的状态,如果用户在线,他们的显示信息中将会有一些扩展的信息,例如他当前正在做什么,是 否希望被打扰等等,详细内容可以参看 Presence 类。 Listening for Roster and Presence Changes Roster 类的典型用途是用树状形式显示组和每一个条目以及它的当前状态。如下图所示是 Exodus XMPP 客户端的花名册。 显示的信息很可能会经常改变,也有可能是花名册的条目被改变甚至被删除。为了监视花名册的改变和显示的信息,应该 使用一个花名册监听器(RosterListener)。以下代码使用 Roster(它可以打印出花名册中的任何变化)注册了一个 RosterListener。标准的客户端应该使用相似的代码更新花名册的用户信息(roster UI)以正确显示变化的信息。 final Roster roster = con.getRoster(); roster.addRosterListener(new RosterListener() { public void rosterModified() { // Ignore event for this example. } public void presenceChanged(String user) { // If the presence is unavailable then "null" will be printed, // which is fine for this example. System.out.println("Presence changed: " + roster.getPresence(user)); } }); 向花名册中添加条目(Adding Entries to the Roster) 花名册和显示使用基于许可的模型,这要求用户在加入别人的花名册前必须得到允许。这样,确保只有被允许的人才可以 看到自己所显示的信息,从而保护了用户的隐私。因此,在你想添加一个新的条目,且对方没有接受你的请求前,该条目 将处于等待状态。 如果另一个用户请求同意显示,从而你他们可以将你加入他们的花名册,你必须接受或拒绝请求。Smack 通过以下三种方 式之一操作同意显示请求: 自动接受所有的同意显示请求。 自动拒绝所有的同意显示请求。 手动处理同意显示请求。 可以使用 Roster.setSubscriptionMode(int subscriptionMode)方法设置模式。简单的客户通常使用一个自动接受或拒绝 同意显示请求的模式,而用更多特征的用户应该使用手动处理同意显示请求的模式,并让终端用户接受或拒绝每一个请求。 如果使用手动模式,应该声明一个信息包监听器(PacketListener)来监听有 Presence.Type.SUBSCRIBE 类型的显示信 息包。 处理收到的信息包(Processing Incoming Packets) Smack 提供一个使用以下两个结构的灵活框架来处理收到的信息包: org.jivesoftware.smack.PacketCollector – 一个允许你同步的等待新的信息包的类 org.jivesoftware.smack.PacketListener – 一个异步的通知你收到信息包的接口 信息包监听器(packet listener)用于事件类型的设计,而信息包收集器(packet collector)有一个信息包的结果队列, 你可以对其实施 polling 和 blocking 操作。所以,信息包监听器在你收到任何一个信息包,且你想对其进行操作时是有用 的,而信息包收集器在你想等待某个特殊的信息包时是有用的。信息包收集器和监听器可以通过 XMPPConnection 的实 例来创建。 由 org.jivesoftware.smack.filter.PacketFilter 接口来决定哪个特殊的信息包将被转交给信息包收集器 (PacketCollector)或信息包监听器(PacketListener)。可以在 org.jivesoftware.smack.filter 包中找到许多预先定义 的过滤器。 以下代码阐释了如何注册一个信息包收集器(packet collector)和信息包监听器(packet listener): // Create a packet filter to listen for new messages from a particular // user. We use an AndFilter to combine two other filters. PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class), new FromContainsFilter("mary@jivesoftware.com")); // Assume we’ve created an XMPPConnection name "connection". // First, register a packet collector using the filter we created. PacketCollector myCollector = connection.createPacketCollector(filter); // Normally, you’d do something with the collector, like wait for new packets. // Next, create a packet listener. We use an anonymous inner class for brevity. PacketListener myListener = new PacketListener() { public void processPacket(Packet packet) { // Do something with the incoming packet here. } }; // Register the listener. connection.addPacketListener(myListener, filter); 标准信息包过滤器(Standard Packet Filters) Smack 包含一套丰富的信息包过滤器,你也可以通过信息包过滤器接口(PacketFilter interface)编写程序来创建自己的 过滤器。缺省的过滤器集包括: PacketTypeFilter – 某个特殊的类类型的信息包过滤器 PacketIDFilter – 拥有特殊的信息包 ID(packet ID)的过滤器 ThreadFilter – 拥有特殊线程 ID(thread ID)的信息包的过滤器 ToContainsFilter –发送到某个特殊地址的信息包的过滤器 FromContainsFilter --发送到某个特殊地址的信息包的过滤器 PacketExtensionFilter – 拥有特殊的信息包扩展的信息包的过滤器 AndFilter –对两个过滤器实施逻辑与操作的过滤器 OrFilter --对两个过滤器实施逻辑或操作的过滤器 NotFilter --对一个过滤器实施逻辑非操作的过滤器 Provider Architecture: Packet Extensions and Custom IQ’s Smack 提供的体系是堵塞自定义的 XML 信息包扩展和 IQ 包分析器的系统(The Smack provider architecture is a syst em for plugging in custom XML parsing of packet extensions and IQ packets)。标准的 Smack 扩展(Smack Exte nsions)是使用提供者的体系结构搭建的。存在以下两种类型的提供者: IQProvider –将 IQ 请求( IQ requests)解析成 Java 对象(Java objects) PacketExtension – 将附属在信息包上的 XML 子文档解析成信息包扩展实例(PacketExtension instances) IQProvider 默认情况下,Smack 致知道如何处理只有类似以下几个名字空间的子信息包的 IQ 信息包(IQ packets): jabber:iq:auth jabber:iq:roster jabber:iq:register 因为许多 IQ 类型是 XMPP 及其扩展部分的一部分,所以提供一个可插入的 IQ 分析机制。IQ Providers 被程序自动的注册 或通过创建在你的 JAR 文件的 META-INF 目录下创建一个 mack.providers 文件。该文件是一个包含一个或多个 iqProvider 条目(iqProvider entries)的 XML 文档,如下例所示: query jabber:iq:time org.jivesoftware.smack.packet.Time 每一个 IQ provider 都和一个元素名(element name)和名字空间( namespace)相联系。在上面的例子中,元素名是 query,名字空间是 abber:iq:time。如果有多重提供者条目(multiple provider entries)尝试注册并控制相同的名字空 间,那么从类路径(classpath)载入的第一个条目将有优先权。 IQ provider 类可以实现 IQProvide 接口,或者继承 IQ 类。在前面的例子中,每一个 IQProvider 负责解析原始的 XML 流 从而创建一个 IQ 实例。在下面的例子中,bean introspection 将被用于尝试自动使用在 IQ packet XML 中发现的值设置 IQ 实例的属性。一个 XMPP 时间信息包如下所示: 20020910T17:58:35 MDT Tue Sep 10 12:58:35 2002 为了让这个信息包自动的映射成上面的 providers file 中所列的时间对象(Time object),它必须有以下几个方法: setUtc(String), setTz(String), 和 setDisplay(String)。自动检查(introspection)的服务将试着自动的将字符串值转化成 a boolean, int, long, float, double,或 Class 类型。转化成何种类型由 IQ 实例的需要来决定。 PacketExtensionProvider 信息包插件提供者(Packet extension providers)为信息包提供一个可插入的系统,这些信息包是一个 IQ, message 和 presence packets 的自定义名字空间的子元素。每一个插件提供者(extension provider)使用一个元素名(element n ame)和名字空间(namespace)在 smack.providers 文件中注册,如下例所示: x jabber:iq:event org.jivesoftware.smack.packet.MessageEvent 如果有多重提供者条目(multiple provider entries)尝试注册并控制相同的名字空间,那么从类路径(classpath)载入 的第一个条目将有优先权。 一旦在一个信息包中发现信息包插件,解析器将传递到正确的提供者。每一个提供者可以实现 PacketExtensionProvider 接口或者是一个标准的 Java Bean。在前面的例子中,每一个插件提供者(extension provider)负责解析原始的 XML 流 去构造一个实例。在下面的例子中,bean introspection 将被用于尝试自动使用在信息包插件子元素(packet extension sub-element)中的值设置类的属性。 当一个插件提供者(extension provider)没有用元素名(element name)和名字空间(namespace)对注册是, Smack 将存储所有在缺省信息包插件(DefaultPacketExtension)对象中的最高级别元素(top-level elements),并匹 配到信息包上。 信息包属性(Packet Properties) Smack 提供简单的机制来将任意的属性附加到信息包上。每一个属性有个字符串类型的名字和一个值,这个值或者是 Java 原始数据类型(int, long, float, double, boolean)的,或者是任何可序列化的对象(Serializable object)(当一个 java 对象实现了 Serializable 接口时,它就是可序列化的)。 使用 API(Using the API) 所有主要对象都有属性 ,例如消息对象(Message objects)。以下代码阐释了如何设置属性: Message message = chat.createMessage(); // Add a Color object as a property. message.setProperty("favoriteColor", new Color(0, 0, 255)); // Add an int as a property. message.setProperty("favoriteNumber", 4); chat.sendMessage(message); 获得这些相同的属性要用到以下的代码: Message message = chat.nextMessage(); // Get a Color object property. Color favoriteColor = (Color)message.getProperty("favoriteColor"); // Get an int property. Note that properties are always returned as // Objects, so we must cast the value to an Integer, then convert // it to an int. int favoriteNumber = ((Integer)message.getProperty("favoriteNumber")).intValue(); 将对象作为属性(Objects as Properties) 将对象作为属性值是改变数据的一个非常有力和简单的方法。但是,你应该记住以下几点: l 信息包插件(Packet extensions)是向 XMPP 增加额外数据的更权威的方式。使用属性在某种情况下也许会比较 方便,但是,Smack 将会控制 XML。 l 当你将 Java 对象(Java object)作为属性发送时,只有在客户机运行的 Java 能够解释数据。所以,可以考虑使 用一系列的原始值来传递数据。 l 作为属性值发送的对象必须实现序列化接口(Serialiable)。除此之外,发送者和接受者都必须由相同版本的类, 否则在反序列化(de-serializing the object)对象时将发生序列化异常。 l 序列化的对象将会非常大,将会占用很多的服务器资源和带宽。 XML 格式(XML Format) 当前的用于发送属性的 XML 格式不是标准的,所以可能不会得到使用 Smack 的客户的认可。XML 如下所示(为了更清晰 添加了注释): prop1 123 blah2 adf612fna9nab 当前支持的数据类型有:integer, long, float, double, boolean, string, 和 java-object。 使用 Smack 调试(Debugging with Smack) Smack 包含两个内置的调试控制台,他们允许你在服务器和客户机建跟踪 XML 的踪迹。简单的调试器(lite debugger) 是 smack.jar 的一部分,加强的调试器(enhanced debugger)包含在(smackx-debug.jar)中。 可以用两种不同的方法激活调试模式: 1. 在创建连接前加入以下一行代码: XMPPConnection.DEBUG_ENABLED = true; 2. 将 Java 的系统属性 smack.debugEnabled 设置为 true。这一系统属性可通过下一命令行设置: java -Dsmack.debugEnabled=true SomeApp 在你的应用程序中,如果你想明确的禁用调试模式,包括使用命令行参数,则在打开新的连接前在你的应用程序中添加以 下一行代码: XMPPConnection.DEBUG_ENABLED = false; Smack 使用一下的逻辑来决定使用哪个调制控制台: 1. 它将首先尝试使用 Java 系统属性 smack.debuggerClass 所指定的调试类(debugger class)。如果你需要开发自 己的调试器 I,可以实现 SmackDebugger 接口然后使用下面的命令行设置系统属性: java -Dsmack.debuggerClass=my.company.com.MyDebugger SomeApp 2. 如果第一步失败了,Smack 就会尝试使用增强的调试器(enhanced debugger)。 文件 smackx-debug.jar 包含, 因此你要把 jar 文件放到类路径(classpath)下。如果空间确定你只是想要配置 smack.jar 文件,这种情况下增强的调试 器(enhanced debugger)将不可用。 3. 最后一种是前面两种都失败后使用简单的调试器(ite debugger)。在你的内存很小的时候,简单的调试器(ite de bugger)是一个很好的选择。 增强的调试器(enhanced debugger) 当调试模式可用时,将出现一个包含每一个创建的连接的标签调试窗口,该窗口包含以下信息: 连接标签(Connection tabs) -- 每一个标签显示连接相关的调试信息 Smack 信息标签(Smack info tab) -- 显示关于 Smack 的信息 (例如: Smack 的版本(Smack version), 安装的组件 (installed components),等等)。 连接标签包含以下信息: 所有的信息包(All Packets) -- 显示由 Smack 解析的发送和收到的信息包的信息。 未经处理的发送信息包(Raw Sent Packets) -- 未经处理的 XML traffic(raw XML traffic)由 Smack 生成并发送至服 务器 。 未经处理的接收信息包(Raw Received Packets) --未经处理的 XML traffic(raw XML traffic)由服务器发送给客户机。 Ad-hoc 消息(Ad-hoc message) -- 允许发送各种类型的 ad-hoc 信息包(ad-hoc packets)。 信息—显示连接状态和统计信息。 简单的调试器(Lite Debugger ) 当调试模式可用时,每创建一个连接将出现调试窗口,该窗口包含以下信息: 客户端的流量(Client Traffic) (红色的文本) --未经处理的 XML traffic(raw XML traffic)由 Smack 生成并发送至服务 器 。 服务器端的流量(Server Traffic)(蓝色的文本) --未经处理的 XML traffic(raw XML traffic)由服务器发送给客户机。 解释的信息包(Interpreted Packets)(绿色的文本) – 显示来自服务器的由 Smack 解析的 XML 信息包(XML packets) 右击任何面板会出现一个菜单,上面有一个选项可以将这些内容拷贝到系统的剪贴板或者清除面板中的内容。
还剩8页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

jilianhui

贡献于2013-10-20

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf