XMPP历史

这个xmpp框架在2008年开始,不过是一个简单地RFC实现。提供一个最小的代理去接受三种xmpp的基本类型presence、message、iq。因为framwork只提供了最小的功能实现,它需要第三方的开发者提供许多拓展的代码。然而,大多数应用使用xmpp需要一些xmpp 拓展 如rosters,capabilities 或者其他的的拓展http://xmpp.org/xmpp-protocols/xmpp-extensions/

非常清楚地,工程需要实现更多的常用的xmpp功能。Roster 支持被添加和一些其他的XEP。早期版本的XEP,拓展是各自开发的,整合大家开发的拓展简直是一个噩梦,而且大部分的拓展并不是必须的,这个时候开发者们觉得保持简单、可通用的拓展是必须要的。

所以第二个版本的工程做成了模块化,工程被分离成一个模块化的系统,以及一个包含多个拓展的文件夹。开发者可以简单地添加他们需要的功能,也让第三方开发者更加容易提交工程。

第三个版本基于核心线程安全,继续使用模块化的代码,更加容易放置多个模块。同时第三方开发者已经成长为了一个开发者社区,不仅仅能够添加模板,还包括修复bug、提供技术支持、测试、文档、建议以及鼓励等。

介绍
xmpp框架分成两部分

  1. xmpp core
  2. 拓展 XEP

XMPPCore 的类

  • XMPPStream
  • XMPPParser
  • XMPPJID
  • XMPPElement
  • XMPPIQ
  • XMPPMessage
  • XMPPPresence
  • XMPPModule
  • XMPPLogging
  • XMPPInternal

XMPPStream
XMPPStream是xmpp的核心,这是你需要接触的主要类,所有的拓展类和定制类需要添加它,它由一些有趣的功能设计,让框架灵活、可拓展和更加容易在它之上开发

XMPPParser 是XMPPStream 使用的一个类,你一般不需要和它打交道

XMPPJID 提供多个JID(Jabber Identifier) 实现,支持解析JID,并解析JID的多种格式,它实现了NSCopying代理,因此JID可以被用作NSDictionary的key。它也实现了NSCoding协议。

XMPPElement 是基本的类,用于三种主要的XMPP 元素 XMPPID,XMPPMessage 和XMPPPresence。 XMPPElement 继承自NSXMLElement

XMPPMddule 提供可选的附加拓展功能,如果你做应用,你可能创建你自己的类,注册和接受代理。然而,如果你正在实现基本的XEP或者你想要添加特定拓展,你需要创建顶层的XMPPModule。

XMPPLoging 提供一个非常快速、高效、灵活的登录框架,之后将详细讲到

XMPPInternal 仅仅是一和core和多个拓展有关的个网络素材

素材:IQ、Message、Presence

继承关系

  • XMPPIQ -> XMPPElement -> NSXMLElement -> NSXMLNode -> NSObject
  • XMPPMessage -> XMPPElement-> NSXMLElement -> NSXMLNode -> NSObject
  • XMPPPresence -> XMPPElement -> NSXMLElement -> NSXMLNode -> NSObjec

NSXML 有一个NSXMLElement+XMPP拓展,这个拓展提供了多个转换方法让你的代码更加简洁可

  1. [element attributeIntValueForName:@"age"];

更多你可以查看 https://github.com/robbiehanson/XMPPFramework/wiki/WorkingWithElements

XMPPStream 配置

配置可以被分成多个部分

  • 配置如何连接xmpp服务器
  • 添加代理
  • 添加模块
  • 连接
  • 校验
  1. 设置stream的myJID属性
  2. xmppStream.myJID = [XMPPJID jidWithString:@"user@gmail.com"];

xmpp stream 会根据XMPP RFC自动最优配置,包括SRV搜索 _xmpp-client._tcp.doman.在以上的例子,使用gmail,谷歌服务器一般返回像这样的字段"talk.googe.com" xmpp stream 将会连接服务器,如果SRV搜索失败,xmpp stream会简单地连接到JID的doman

如果你知道你连接到一个xmpp server,并且这个server没有SRV记录,你能够告诉xmpp stream 跳过SRV搜索,如下

  1. xmppStream.myJID = [XMPPJID jidWithString:@"user@myCompany.com"];
  2. xmppStream.hostName = @"myCompany.com";

当你使用一个开发xmpp 服务器,hostname 同样可以找到,服务器可能仅仅在本地网络可用,没有dns 地址,你可以这样做

  1. xmppStream.myJID = [XMPPJID jidWithString:@"user@dev1.myCompany.com"];
  2. xmppStream.hostName = @"192.168.2.27";

另一个可选的属性是端口,默认端口是5222,如果你的服务器端口不一样,你需要设置hostPort属性

添加代理

MulticastDelegate介绍
xmpp框架需要支持一个不限制个数的拓展,包括官方的拓展、以及你希望添加到框架中的拓展。所以普通的代理模式不会起作用。XMPP模块和拓展需要被分开到不同的类中,然而每一个类都需要接受代理的回调,而基本的NSNotifaciton不能满足要求,应为一些代理需要返回一个值。

因此MulticastDelegate 允许你使用基本的代理,同时也允许多个类接受相同的代理通知。这样设计妙在: 你不需要把所有的xmpp 句柄代码放在单个类中,你能够根据功能把分开放。

  1. 添加和移除XMPPStream delegate
  2. [xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
  3. ...
  4. [xmppStream removeDelegate:self];

添加modules
xmpp框架自带了一些拓展,当然你也可以写你希望的拓展,我们不会review任何可用的拓展,但我们会列一些例子

XMPPReconnect     意外断开会自动重连
XMPPRoster            提供基本的roster名册
XMPPRoom             提供多用户聊天支持
XMPPPubSub         公开subscribe
如下:

  1. xmppReconnect = [ [XMPPReconnect alloc] init];
  2. // Optional configuration of xmppReconnect could go here.
  3. // The defaults are fine for our purposes.
  4. [xmppReconnect activate:xmppStream];
  5. // You can also optionally add delegates to the module.
  6. [xmppReconnect addDelegate:self delegateQueue:dispatch_get_main_queue()];
  7. // And that's all that is needed.
  8. // The module will receive any delegate methods it needs automatically
  9. // from the xmpp stream, and will continue to do its thing unless you deactivate it.

连接
如果你准备好了,我们开始连接

  1. NSError *error = nil;
  2. if (![xmppStream connect:&error])
  3. {
  4. NSLog(@"Oops, I probably forgot something: %@", error);
  5. }

如果你忘记了设置必须的属性,如myJID,连接方法会返回NO,error message里面会有详细信息

在连接过程中,客户端和服务端完成一个xmpp 握手,服务器提示客户端,可用的它支持的或者必须的代理。一些服务器可能需要安全连接通过SSL。/TLS. 这种情况,会自动建立安全连接。如果你连接到服务器使用一个不正确的X509证书,你需要实现xmppStream:willSecureWithSettings: 代理方法去顶默认的安全设置

确认
在握手连接已经完成后, xmppStreamDidConnect:delegate 方法被激发,这个时候大部分的客户端需要开始确认过程如下

  1. - (void)xmppStreamDidConnect:(XMPPStream *)sender
  2. {
  3. [xmppStream authenticateWithPassword:password error:NULL];
  4. }

XMPP logging
xmpp的log有几个目标

1. 支持多级别的log

不是所有log信息有相同的优先级别,如error 这样的,当其他的仅仅是information。级别帮助开发者保持log信息完整,以及方便的开关log的能力

2. 必须可在一个文件中可配置。当frame包含很多文件,一个全局level 的log不会切。添加debug 一个时间通常意味着开发者仅想在少量文件里看到log的状态

3. 必须可在终端用户配置
xmpp framework的使用者需要根据log报告全局掌控发生了什么。用于有不同的需求,一些想要log报告写到文件中,其他的可能想要log报告写到数据库,或者放到不同的位置基于log报告是来自应用还是来自xmpp framwork。
我开发了很多客户端,我看见很多连接第三方框架一次又一次地出现相同的问题。第三方库散乱的log语句。需要用户注释掉NSLog 语句,或者通过宏定义转化

所以与其被笨笨的NSLog打败,xmpp framework 使用了一个专业的log 框架CocoaLumberjack 
这个log框架事实上有时候做同样的事比NSLog 快。同时它还支持不同搞得配置,允许用户添加自己的log语句,添加其他的格式。

下面你需要知道如何把log  连接到XMPPFramework
框架中大部分文件你能够发现以下的两行

  1. // Log levels: off, error, warn, info, verbose
  2. static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN;

你可以看到,有四个级别的log

  • Error
  • Warning
  • Info
  • Verbose

你可以更改任何文件的 log 级别,让它打印出更多的信息

这里有个标记能够被设置,当tracing 是YES,打印被调用的方法

请注意tracing 是被和 log levels 分开的,如可以设置log等级为warning,同时允许标记如下

  1. // Log levels: off, error, warn, info, verbose
  2. static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN | XMPP_LOG_FLAG_TRACE;

在代码中,意味着

  1. XMPPLogTrace(); // Enabled - Will spit out "<FileName>: <MethodName>"
  2. XMPPLogError(@"I will get logged");
  3. XMPPLogWarn(@"I will get logged");
  4. XMPPLogInfo(@"I will NOT get logged");
  5. XMPPLogVerbose(@"I will NOT get logged");

xmppStream 有个选项,让你可以看见要发送和接受的 xml ,你能够把它转成XMPPStream如下
// Log levels: off, error, warn, info, verbose
static const int xmppLogLevel = XMPP_LOG_LEVEL_INFO | XMPP_LOG_FLAG_SEND_RECV;

log 的目标是让你控制和得到log 语句执行到哪里了,这意味着你需要配置lumberjack框架当你的程序启动了,为了启动,你能够在appdelegate 做些事情

  1. #import "DDLog.h"
  2. #import "DDTTYLogger.h"
  3. - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
  4. {
  5. [DDLog addLogger:[DDTTYLogger sharedInstance] withLogLevel:XMPP_LOG_FLAG_SEND_RECV];
  6. // All your other code...
  7. }

更多关于 CocoaLumberJack 消息你能够在它的工程页面中查看 CocoaLumberJack gitHub页
我非常乐意看到你在自己的应用中使用专业的logging 框架,一旦你使用了,你将离不开它 :)

 

李洪强iOS开发之XMPP的更多相关文章

  1. 李洪强iOS开发之Block和协议

    李洪强iOS开发之Block和协议 OC语言BLOCK和协议 一.BOLCK (一)简介 BLOCK是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任 ...

  2. 李洪强iOS开发之iOS社区收集

    李洪强iOS开发之iOS社区收集 项目 简述 github 全球最大的代码仓库,无论是iOS开发还是Android开发没有人不知道这个网站,它也是一个社区,你可以去follow(关注)某些人或公司. ...

  3. 李洪强iOS开发之iOS工具收集

    李洪强iOS开发之iOS工具收集 项目 简述 日期 我是怎么慢慢变懒的 : Jenkins + 蒲公英 使用Jenkins + 蒲公英使得项目打包给测试人员自动化,大大节省了劳动力 2015.04.1 ...

  4. 李洪强iOS开发之iOS学习方法收集

    李洪强iOS开发之iOS学习方法收集 在这里收集一些iOS学习方法,会不断更新 项目 简述 日期 一年多iOS开发总结 作者总结了自己一年多的iOS学习经验,对于iOS初学者来说很多地方是可以借鉴的 ...

  5. 李洪强iOS开发之iOS好文章收集

    李洪强iOS开发之iOS好文章收集 该文收集朋友们转发或自己的写的技术文章,如果你也有相关的好文章,欢迎留言,当好文章多的时候,我会对这些好文章进行分门别类 文章 简述 日期 直播服务配置 使用 ng ...

  6. 李洪强IOS开发之iOS好项目收集

    李洪强IOS开发之iOS好项目收集 在这里收集一些最近出现的比较实用好玩的框架或者项目,会不断更新 项目 简述 日期 SCTableViewCell 类似与QQ侧滑删除Cell的Demo 201501 ...

  7. 李洪强iOS开发之iOS技术博客

    李洪强iOS开发之iOS技术博客 注意:访问博客请直接点击博客,不要点击后面的RSS地址 博客地址 RSS地址 南峰子的技术博客   剑尖博客   图拉鼎   Henry Lee   Dev Talk ...

  8. 李洪强iOS开发之带placeHolder的Textview

    李洪强iOS开发之带placeHolder的Textview  01 - 创建工过程,定义全局属性,遵守textview的代理协议  02 - 添加一个textview和一个label 03 - 实现 ...

  9. 李洪强iOS开发之RunLoop的原理和核心机制

    李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...

随机推荐

  1. AE实现投影定义和投影转换

    添加引用ESRI.ArcGIS.DataManagementTools 1.获取要定义和要转换的投影 IWorkspaceFactory wsf = new ShapefileWorkspaceFac ...

  2. UML静态类图

    0,主要分为类.接口.协作.关系,这四种元素.作用:a,显示类.接口以及他们之间的静态结构和关系:b,用于描述系统的结构化设计. 1,类 CStudent +m_strName : string +S ...

  3. sphinx 占用大量内存

    http://www.coreseek.com/forum/2_1847_0.html(转) 刚开始没改下面2句时,内存占用比较多,在生成index的时候就占用了! 下面是解决方法: 每个索引中写上 ...

  4. js中 在数组中删除重复的元素(自保留一个)

    例如:var student = [‘qiang’,’ming’,’tao’,’li’,’liang’,’you’,’qiang’,’tao’]; 第一种思路是:遍历要删除的数组arr, 把元素分别放 ...

  5. JasperReport原理解析之(一)

    1. [加载原始文件]有iReport生成jrxml文件后,由jasperreport包中的类JRXml文件 加载和解析 jrxml文件. 文件解析后生成  JasperDesign对象. Jaspe ...

  6. Asp.net 引用css/js资源文件

    注意Page.ResolveUrl之前的双引号,不是单引号 <script type="text/javascript" src="<%= Page.Reso ...

  7. php 字母大小写转换的函数

    分享下,在php编程中,将字母大小写进行转换的常用函数. 1.将字符串转换成小写strtolower(): 该函数将传入的字符串参数所有的字符都转换成小写,并以小定形式放回这个字符串 2.将字符转成大 ...

  8. Python字符串内建处理函数

    #coding=utf-8 __author__ = 'Administrator' # 字符串处理函数 s1 = "study python string function , I lov ...

  9. 【Python笔记】异常处理

    1 什么是异常 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误. 当Pytho ...

  10. Android UI效果实现——滑动模糊渐变效果实现

    前言: 大家应该都看到过iOS7解锁屏幕的滑动模糊渐变效果,好了,现在可以把手纸收起来了,今天黄老师就给大家讲一下如何在Android平台上 实现类似的滑动模糊渐变效果,其实方式远比你想像的简单. 目 ...