XMPP

iOS 的 XMPP framework 简介

登陆 - 验证密码上线 - 断开 - 好友状态 - 接收消息和发送消息 - 获取好友信息(列表&名片)和添加删除好友 - 聊天室 - 消息回执 - 添加AutoPing 为了监听服务器是否有效,增加心跳监听。


XMPP 协议简单介绍

1. 为什么选择XMPP协议

2. XMPP的基本网络结构 - 2.1 XMPP客户端 - 2.2 XMPP服务器 - 2.3 XMPP网关

3. 服务器端介绍 - 3.1 什么是Openfire - 3.2 为什么使用Openfire

4. XMPP协议的组成 RFC 3920 XMPP

5. XMPP地址格式

6. XMPP消息格式 - 6.1 message type属性 + to属性 + from属性 - 6.2 presence - 6.3 iq (Info / Query)


《移动IM开发那些事》

通讯方式选择 - P2P + 服务器中转

网络连接方式 - 基于TCP的长连接 + 基于HTTP短连接PULL的方式

协议选择 - XMPP + SIP + MQTT + 私有协议

私有协议的设计 - 序列化选择 + 协议格式设计

其他问题 - 协议加密 + 快速连接(登录) + 连接保持 + 消息可达 + 文件上传优化


Overview of the XMPP Framework

Up to date instructions on how to install XMPP Framework manually?

Introduction


框架分为2个部分:

1. XMPP Core

2. The extensions (roster, XEP's, optional supporting utilities, etc)

拓展包含如名单支持,自动重连和多样的XMPP拓展实现。


XMPP Core {#core}


XMPP框架的核心文件在 "Core" 文件夹中,文件如下:

XMPPStream

XMPPParser

XMPPJID

XMPPElement

XMPPIQ

XMPPMessage

XMPPPresence

XMPPModule

XMPPLogging

XMPPInternal

框架的核心是 XMPPStream 类,这是你主要用到的类,同时这个类是所有拓展和自定义代码要接入的地方。它有许多有趣的特性,被用于使框架灵活,可拓展,易于从上层开发。我们将在本文档的后面深入的讨论这些。

XMPPParser  XMPPStream 的内部类。你可以大胆的猜想它是干嘛的。在任何情况下,你都不需要与 parser 打交道。

XMPPJID 提供了一个不可变的 JID (Jabber Identifier)实现。它支持 JID's 解析,同时抽取了JID在多种形式下的不同部分。它遵循 NSCopying 协议,以便 JID's 可能用作 NSDictionary 中的keys。也遵循 NSCoding 协议。

XMPPElement 是3个主要的 XMPP 元素的基础类: XMPPIQ & XMPPMessage & XMPPPresence。其拓展了 NSXMLElement,因此你拥有整 NSXML foundation 用于观察任何 XML元素。更多细节在 section Elements: IQ, Message, & Presence.

XMPPModule 为可选可拓展提供了基础类。如果自己写app,就会想创建自己的类,注册获得自己的delegate调用。

XMPPLogging 提供快速,强大,灵活的日志框架。XMPP Logging

XMPPInternal 关联 core 和多种高级底层的拓展


Elements: IQ, Message, & Presence


XMPPElement 扩展 NSXMLElement,因此你拥有整 NSXML foundation 用于观察任何 XML元素。

XMPPIQ -> XMPPElement -> NSXMLElement -> NSXMLNode -> NSObject

XMPPMessage -> XMPPElement -> NSXMLElement -> NSXMLNode -> NSObject

XMPPPresence -> XMPPElement -> NSXMLElement -> NSXMLNode -> NSObject

除了 NSXML foundation,框架提供 NSXMLElement+XMPP 分类,有多样的便利方法来确保编码更加精确可读。如:

[element  attributeIntValueForName:@"age"];

更多信息,戳 Working With Elements


XMPPStream Configuration {#configuration}


XMPPStream 实例的配置分为几步:

Configuring how to connect to the xmpp server

Adding delegates

Adding modules

Connecting

Authenticating


Configuring the connection

对大多数人,只需简单一步,设置 stream 的 myJID 属性。如:

xmppStream.myJID = [XMPP   JIDjidWithString:@"[email protected]"];

The xmpp stream will figure out the rest by following the XMPP RFC. This involves doing an SRV 搜索 for _xmpp-client._tcp.domain。上面的列子,用 gmail, google 服务器将很可能返回像 "talk.google.com",之后 xmppStream 将连接服务器。如果 SRV 搜索失败,之后 xmppStream 将简单的连接 JID's 域名。

如果你知道连接的 xmpp 服务器没有 xmpp SRV 记录,你能告诉 xmppStream 跳过 SRV 搜索,通过指定 hostName。如

xmppStream.myJID = [XMPP  JIDjidWithString:@"[email protected]"];

xmppStream.hostName = @"myCompany.com";

当你用一个开发 xmpp 服务器,hostname 也很容易得到。但是服务器仅能在本地网络获得,或者没有 DNS 地址。如:

xmppStream.myJID = [XMPP  JIDjidWithString:@"[email protected]"];

xmppStream.hostName =@"192.168.2.27";

另一个可选属性是 hostPort。默认,根据 xmpp 说明,几乎所有服务器运行 port 5222。但是,如果你的服务器运行不同的 port,你也能设置 hostPort 属性。


Adding Delegates

XMPPStream 有许多有趣的特性,被用于使框架灵活,可拓展,易于从上层开发。其中之一就是运用 MulticastDelegate。

What is a MulticastDelegate?

xmpp 框架需要支持一个非限制数量的拓展。这包含官方拓展,也包含其他拓展或者自定义代码。因此传统的代理模式不行了。XMPP 模块和拓展需要被分离为他们自己独立的类,然而,所有这些类需要获得 delegate 方法。同时,标准的 NSNotification 架构也不起作用了,因为一些代理要求一个返回值。(而且,从 notification 的 userInfo 字典中提取参数真TM烦人)

因此一个多播代理允许你用标准模式接入框架,但是它允许多类获得相同的 delegate 通知。好处在于你可以把所有 xmpp 处理代码放进一个类中。也能分离处理代码到多个类中,一切由你决定。

你能在任何时候把自己作为一个XMPPStream的 delegate 添加 / 删除。

[xmppStream   addDelegate:self    delegateQueue:dispatch_get_main_queue()];...

[xmppStream   removeDelegate:self];

关于多播代理的更多细节 here    关于线程和队列的更多细节 here


Adding Modules

框架中附带许多拓展,当然,你想写多少就写多少。我们不可能 review 所有拓展,但是我们将列举一些

XMPPReconnect - 如果意外断连,自动重连流

XMPPRoster - provides support for standard xmpp roster.

XMPPRoom - provides multi-user chat support.

XMPPPubSub - Publish subscribe

例如,我们将接入 XMPPReconnect 到我们的流中

xmppReconnect = [ [XMPPReconnect   alloc]   init];

// xmppReconnect 的可选配置写这儿

// The defaults are fine for our purposes.

[xmppReconnect   activate:xmppStream];

// 你也可以选择性的为模块增加 delegates

[xmppReconnect   addDelegate:self   delegateQueue:dispatch_get_main_queue()];

// 这就是所有需要做的

// 从 xmpp 流,模块将自动获得任何它需要的 delegate 方法,同时继续做它的事情。除非失效。


Connecting

当你准备好了,你可以开始连接过程:

NSError *error = nil;

if  ( ![xmppStream   connect:&error] )   {

      NSLog(@"Oops, I probably forgot something:%@", error);

}

如果你忘记设置必要的属性,如 myJID,之后连接方法将返回 NO,同时 error 信息将通知你。

在连接过程中,客户端和服务器将经历 xmpp 握手。其中,服务器通知客户端多种协议,有它支持的,也有要求的。一些服务器可能要求通过 SSL/TLS (startTLS) 安全连接。如果是这样的话,xmppStream 将自动安全连接。如果你连接服务器,用不合适的 X509 证书,你可能需要实现xmppStream:willSecureWithSettings: 代理方法来警告默认安全设置。


Authenticating

在所有连接握手完成之后,xmppStreamDidConnect: 代理方法被调用。这是一般大多数客户端应该开始验证过程的地方。很简单:

- (void)xmppStreamDidConnect:(XMPPStream *)sender  {  

     [xmppStream   authenticateWithPassword:password   error:NULL];

}


XMPP Logging

通过 xmpp 框架的 logging 有几个目的:

必须支持几个 log 等级

不是所有 log 信息都有相同的优先级。有些关于 errors,而有些只是信息。levels 帮助开发者保持他们的日志信息完整,无障碍的打开关闭它们的能力。

必须基于每个文件可配置

必须对最终用户可配置


xmpp framework 用专业 log 框架:CocoaLumberjack,特别厉害。

这里有你需要知道的关于 XMPPFramework 如何 logging

框架中大多数文件的头部,会发现:

// Log levels: off, error, warn, info, verbose

static  const  int  xmppLogLevel = XMPP_LOG_LEVEL_WARN;

看到了吧,有4种 log levels (还有 XMPP_LOG_LEVEL_NONE)

Error

Warning

Info

Verbose

你能改变任何文件的 log level 来获得更多信息。

此外,有一个 Trace flag 可以用,当 enabled,将打印被调用的方法。

记住,tracing独立于 log levels,如,同时设置:

// Log levels: off, error, warn, info, verbose

static  const  int  xmppLogLevel = XMPP_LOG_LEVEL_WARN | XMPP_LOG_FLAG_TRACE;

就代码而言,这表示

XMPPLogTrace();  // Enabled - Will spit out " : "

XMPPLogError(@"I will get logged");

XMPPLogWarn(@"I will get logged");

XMPPLogInfo(@"I will NOT get logged");

XMPPLogVerbose(@"I will NOT get logged");

此外,XMPPStream有一个可选的,允许你查看 raw XML 被发送和接受。在 XMPPStream.m 中打开:

// Log levels: off, error, warn, info, verbose

static  const  int  xmppLogLevel = XMPP_LOG_LEVEL_INFO | XMPP_LOG_FLAG_SEND_RECV;

回调所有 logging 的目的是让你控制什么被log和这些log的状态。所以当app启动时,你将配置 lumberjack 框架。对于新手,下面这样配:in your AppDelegate

#import  "DDLog.h"

#import  "DDTTYLogger.h"

- (void)applicationDidFinishLaunching:(NSNotification*)aNotification  {    

     [DDLog  addLogger:

                   [DDTTYLogger  sharedInstance]  withLogLevel:XMPP_LOG_FLAG_SEND_RECV];

}

更多关于 Lumberjack 信息 project page。

你可能感兴趣的:(XMPP)