1.XMPPFramework框架分为两个部分:
(1)XMPP Core(实现了XMPP规范<RFC 3920>)
(2)XMPP Extensions(rester,XEP,utiliites)
2.XMPP Core
XMPP核心文件包含在XMPP框架的Core文件夹下,包括下面一些文件:
XMPPStream:该类是整个框架的核心类,它是你将交互的主要类,并且它是所有的扩展和自定义代码插入类。它提供一些旨在使框架灵活,可扩展,易于开发之上的有趣的功能。
XMPPParser:XMPPParser是用于XMPPStream内部类。你也许可以大胆的猜测它做什么。你不需要以任何方式,形状或形式与之交互。
XMPPJID:XMPPJID提供了一个不可变的JID(Jabber的标识符)实现。它支持JID的解析,并且能在各种形式下提取JID的各部分。它符合NSCopying协议,所以JID可被用作在NSDictionary的key。它也符合NSCoding协议。
XMPPElement:XMPPElement是3个主要的XMPP元素的基类:XMPPIQ、XMPPMessage、XMPPPresence。XMPPElement继承自NSXMLElement,所以你需要知道整个NSXML基础,以便检查任意的xml元素。
XMPPModule:为可选可插拔扩展提供了基础类。如果您正在编写自己的应用程序特定(专有)的代码,你将很可能只是创建自己的类并注册接受委托的调用。但是,如果要实现一个标准的XEP,或者你希望你的应用程序特定的扩展是可插拔的,那么你就可以建立在XMPPModule之上。
XMPPLogging:提供了一个非常快,功能强大且灵活的日志框架。
XMPPInternal:仅仅是内部的东西的相关核心和各种先进的低层次的扩展。
3.Elements:IQ,Message,Presence
他们的继承关系如下:
XMPPIQ - > XMPPElement - > NSXMLElement - > NSXMLNode - > NSObject
XMPPMessage - > XMPPElement - > NSXMLElement - > NSXMLNode - > NSObject
XMPPPresence - > XMPPElement - > NSXMLElement - > NSXMLNode - > NSObject
除了NSXML基础,框架也提供一个NSXMLElement+XMPP的类别。这个类别提供了各种方便的方法,使你的代码更加简洁易读。例如:
[element attributeIntValueForName:@"age"];
4.XMPPStream的配置
XMPPStream的配置包括下面多个部分:
(1)配置如何连接到XMPP服务器
(2)添加代理
(3)添加模型
(4)连接
(5)生效
一、配置连接:
对大多数人来说,这里仅仅只涉及一个步骤:为stream设置myJID属性值。如:
xmppStream.myJID = [XMPPJID jidWithString:@"[email protected]"];
XMPP流将找出遵循XMPP RFC的域。这涉及到做一个SRV查找_xmpp-client._tcp.domain。在上面的例子中,使用Gmail,谷歌的服务器可能会返回类似“talk.google.com”,而XMPP流将连接到该服务器。如果SRV查找失败,那么XMPP流将简单地连接到JID的域。
如果你知道你正在连接到一个没有XMPP SRV记录的XMPP服务器,你可以告诉XMPP流跳过SRV,查找指定的主机名。例如:
xmppStream.myJID = [XMPPJID jidWithString:@"[email protected]"]; xmppStream.hostName = @"myCompany.com";
主机名也会派上用场,当你使用的是一个开发的XMPP服务器。也许该服务器只是在本地网络上可用,或者不具有DNS地址等。例如:
xmppStream.myJID = [XMPPJID jidWithString:@"[email protected]"]; xmppStream.hostName = @"192.168.2.27";
另一个可选的属性是HOSTPORT。默认情况下,按照XMPP规范,几乎所有服务器上的端口是运行在5222上。然而,如果你的服务器在不同的端口上运行,你可以设置HOSTPORT属性。
二、添加代理:
XMPPStream有一些旨在使框架灵活,可扩展,易开发之上有趣的功能。其中之一是利用MulticastDelegate。
那么,什么是MulticastDelegate?
XMPP框架需要支持无限数量的扩展。这包括框架的官方扩展,以及您可能想要插入框架的自定义代码或者扩展。因此,传统的代理模式行不通。XMPP模块和扩展需要分开到自己单独的类,但每个类都需要接受委托方法。标准的NSNotification架构也不能工作,因为有些代理要求返回值。(加上从通知的用户信息字典中提取参数真的很烦人。)
所以MulticastDelegate允许你使用标准委托范式插入到框架中,但它允许多个类去接收相同的委托通知。这样做的好处是,你不必把所有的XMPP处理代码放在一个类中。你可以在多个类中分开处理,或者你认为合适的方式。
您可以添加/删除自己的XMPPStream委托在任何时候:
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; ... [xmppStream removeDelegate:self];
如何使用MulticastDelegate?
在客户端,你可以像这样做:
//添加self做为delegate,告诉xmppStream在主线程中调用委托方法 [xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; //然后像实现正常代理一个实现你需要的方法 - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message { ... }
正如你所看到的,这是非常类似于传统的代理模式,但是扩展到允许您能指定线程的具体信息。
如果你决定在其它线程中调用代理方法该怎么做呢,同样很简单:
//大多数事物是在主线程中处理 [xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; //但是,如果是一个缓慢的事情,可以放在后台队列,这样就不会减慢UI了 [xmppStream addDelegate:bgProcessor delegateQueue:bgProcessorQueue];
在iPhone环境中,这将成为一个非常强大的工具,维护您的应用程序的性能。
在我自己的插件,我将如何使用它?
为了使用MulticastDelegate,作为一个广播员(broadcaster),你需要声明并初始化它。像这样:
GCDMulticastDelegate <MyPluginDelegate> *multicastDelegate; multicastDelegate = (GCDMulticastDelegate <MyPluginDelegate> *)[[GCDMulticastDelegate alloc] init];
然后添加方法,这些方法允许其它对象能够添加、移除他们自己从代理列表中:
- (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue { [multicastDelegate addDelegate:delegate delegateQueue:delegateQueue]; } - (void)removeDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue { [multicastDelegate removeDelegate:delegate delegateQueue:delegateQueue]; }
如果你是继承自XMPPModule,上面这些方法会自动实现。
当你想发出一个委托方法,对所有注册的委托,你可以简单地这样做:
[multicastDelegate worker:self didFinishSubTask:subtask inDuration:elapsed];
multicastDelegate会调用所有的代理,在dispatch_async()上调用他们相关联的dispatch_queue
三、添加模型:
有一些附带的框架的扩展,当然,你可以随意写的许多扩展。下面是几个例子:
XMPPReconnect - 自动重新连接,如果你得到意外断开的流(连接)。
XMPPRoster - 提供了标准的XMPP名册支持。
XMPPRoom - 提供多用户聊天支持。
XMPPPubSub - 发布订阅
下面的例子是将XMPPReconnect模型插件加入到我们的流中:
[ XMPPReconnect alloc] init]; // 可以在这里面对xmppReconnect进行可选配置。 [ xmppReconnect activate:xmppStream]; //你也可以选择添加代理模块。 [ xmppReconnect addDelegate:self delegateQueue:dispatch_get_main_queue()] ; //这就是所有需要的。 //该模块将自动接收需要的任何委托方法 //从XMPP流,并且将持续工作,除非您关闭它。
四、连接:
当你准备好了,就可以开始连接过程:
NSError *error = nil; if (![xmppStream connect:&error]) { NSLog(@"Oops, I probably forgot something: %@", error); }
如果忘记了设置所需属性,诸如myJID,则连接方法将返回NO,并且该错误消息将通知你问题所在。
在连接过程中,在客户端和服务器通过一次XMPP握手。在这段时间内,服务器通知很好支持了各种协议的客户端。有些服务器可能需要通过SSL/TLS( STARTTLS)保证连接的安全。如果是这样的情况下,XMPP流将自动进行安全连接。如果你正在使用不正确的X509证书连接服务器,则可能需要实现xmppStream:willSecureWithSettings:委托方法来改变默认的安全设置。
五、生效:
在连接握手完成后,xmppStreamDidConnect:委托方法被调用。这通常是大多数客户端应该开始认证过程。
- (void)xmppStreamDidConnect:(XMPPStream *)sender { [xmppStream authenticateWithPassword:password error:NULL]; }
说明:本文为翻译自XMPPFramework官方文档。