iOS —— XMPP 详解
iOS - XMPP 的使用
转载 https://www.cnblogs.com/QianChia/p/6411914.html
1、XMPP
-
XMPP 是一个基于 Socket 通信的即时通讯的协议,它规范了即时通信在网络上数据的传输格式,比如登录,获取好友列表等等的格式。XMPP 在网络传输的数据是 XML 格式。
-
开发架构:
-
iOS 框架:XMPPFramework
-
服务器:Openfire
-
数据库:MySQL
2、XMPPFramework 框架简介
2.1 XMPPFramework 简介
- XMPPFramework 是一个 OS X/iOS 平台的开源项目,使用 Objective-C 实现了 XMPP 协议(RFC-3920),同时还提供了用于读写 XML 的工具,大大简化了基于 XMPP 的通信应用的开发。
2.2 XMPPFramework 结构
-
1、XMPPFramework 的目录结构如下:
目录 说明 Authentication 授权,与授权验证相关,如用户名密码等 Categories 分类,XMPP 自己写的一些分类,尤其是 NSXMLElement+XMPP 扩展是必备的 Core 核心,这里是 XMPP 的核心文件目录,我们最主要的目光还是要放在这个目录上 Extensions 扩展,XMPP 的扩展模块,用于扩展各种协议和各种独立的功能,其下每个子目录都是对应的一个单独的子功能 Utilities 工具,都是辅助类,我们开发者不用关心这里 Vendor 第三方库,这个目录是 XMPP 所引用的第三方类库,我们也不用关心这里 -
虽然这里有很多个目录,但是我们在开发中基本只关心 Core 和 Extensions 这两个目录下的类。
-
在 Core 中:
目录 说明 XMPPElement 是一个基类,延展出三个子类 XMPPIQ 请求,用户登录,用户注册,添加好友等 XMPPMessage 消息,用来发各种消息等 XMPPPresence 展现,用户上线下线提示等 XMPPStream 流,非常常用,大部分类的加载都在写在流的懒加载里 -
在 Extensions 中:
目录 说明 CoreDataStorage coreData 存储 Reconnect 重新连接 Roster 好友管理 SystemInputActivityMonitor 系统输入的活动监控 -
在 Vendor 中:
文件夹 说明 CocoaAsyncSocket 异步 Socket CocoaLumberjack ⽇志相关 KissXML XML 解析
-
-
2、XMPPFramework 中常用的类:
类 说明 XMPPStream XMPP 基础服务类 XMPPRoster 好友列表类 XMPPUserCoreDataStorageObject 管理用户的类 XMPPRosterCoreDataStorage 好友列表(用户账号)在 core data 中的操作类 XMPPvCardCoreDataStorage 好友名片(昵称,签名,性别,年龄等信息)在 core data 中的操作类 XMPPvCardTemp 好友名片实体类,从数据库里取出来的都是它 xmppvCardAvatarModule 好友头像 XMPPReconnect 如果失去连接,自动重连 XMPPRoom 提供多用户聊天支持 XMPPPubSub 发布订阅 XMPPMessageArchiving 其中有数据表 XMPPMessageArchiving_Message_CoreDataObject 取出当前信息的类 -
3、XMPPFramework 几个常用到的扩展协议:
协议 协议简介 XEP-0006 使能与网络上某个 XMPP 实体间的通信 XEP-0009 在两个 XMPP 实体间传输 XML-RPC 编码请求和响应 XEP-0012 最后的活动(判断上线,离开断开) XEP-0045 多人聊天相关协议 XEP-0054 名片格式的标准文档,个人信息设置 XEP-0060 提供通用公共订阅功能 XEP-0065 两个 XMPP 用户之间建立一个带外流,主要用于文件传输,sockets5 字节流 XEP-0066 二进制数据传输(特殊信息的发送) XEP-0082 日期和时间信息的标准化表示 XEP-0085 聊天对话中通知用户状态,聊天状态通知 XEP-0100 表述了 XMPP 客户端与提供传统的 IM 服务的代理网关之间交换的最佳实践 XEP-0115 广播和动态发现客户端、设备、或一般实体能力 XEP-0136 为服务端备份和检索 XMPP 消息定义机制和偏好设置,聊天记录归档 XEP-0153 用于交换用户头像,基于名片的头像 XEP-0184 消息送达回执协议 XEP-0199 XMPP ping 协议(用来 ping 服务器和 ping 自己) XEP-0202 用于交换实体间的本地时间信息 XEP-0203 用于延迟发送 XEP-0224 引起另一个用户注意的协议 XEP-0335 JSON 容器(可能以后某些信息传输将用 JSON 格式) -
XMPP 的扩展协议 Jingle 使得其支持语音和视频,目前 iOS 尚不支持。
-
iOS 发送附件(图片,语音,文档…)时比较麻烦,XMPP 框架没有提供发送附件的功能,需要自己实现。
-
iOS 发送附件实现方法:
- 1、将获取到的图片/音频文件通过 base64 加密,直接通过 xmpp 的消息体发送过去,然后解码。
-
2、通过 http 请求的方式将图片/音频文件上传到服务器,然后将图片/音频文件的下载地址通过 xmpp 消息体发送过去,另外一个客户端下载。
-
音频文件建议转码为 amr,这种格式的音频文件比较小。
-
-
2.3 XMPPJID 类
-
登录需要到账号,而所谓的账号其实就是用户唯一标识符(JID),在 XMPP 中使用 XMPPJID 类来表示。
-
JID 一般由三部分构成:用户名,域名和资源名,格式为
[email protected]/resource
,例如:[email protected]/Anthony
。对应于 XMPPJID 类中的三个属性 user、domain、resource。 -
如果没有设置主机名(HOST),则使用 JID 的域名(domain)作为主机名,而端口号是可选的,默认是 5222,一般也没有必要改动它。
2.4 XMPPStream 类
-
我们要与服务器连接,就必须通过 XMPPStream 类了,它提供了很多的 API 和属性设置,通过 socket 来实现的。Verdor 目录包含了 CocoaAsyncSocket 这个非常有名的 socket 编程库。XMPPStream 类还遵守并实现了 GCDAsyncSocketDelegate 代理,用于客户端与服务器交互。
-
当我们创建 XMPPStream 对象后,我们需要设置代理,才能回调我们的代理方法,这个是支持 multicast delegate,也就是说对于一个 XMPPStream 对象,可以设置多个代理对象,其中协议是XMPPStreamDelegate。
-
而当我们不希望某个 XMPPStream 对象继续接收到代理回调时,我们通过这样的方式来移除代理。
-
接下来,我们要设置主机和端口,通过设置这两个属性。
-
XMPPStream 有 XMPPJID 类对象作为属性,标识用户,因为我们后续很多操作都需要到 myJID。
-
而管理用户在线状态的就交由 XMPPPresence 类了,它同样被作为 XMPPStream 的属性,组合到 XMPPStream 中,后续很多关于用户的操作是需要到处理用户状态的。
2.5 XMPPStreamDelegate
-
这个协议是非常关键的,我们的很多主要操作都集中在这个协议的代理回调上。它分为好几种类型的代理 API,比如授权的、注册的、安全的等。
2.6 XMPPIQ 类
-
消息查询(IQ)就是通过此类来处理的了。XMPP 给我们提供了 IQ 方便创建的类,用于快速生成 XML 数据。
-
IQ 是一种请求/响应机制,从一个实体发送请求,另外一个实体接受请求并进行响应。例如,Client 在 stream 的上下文中插入一个元素,向 Server 请求得到自己的好友列表,Server 返回一个,里面是请求的结果。
-
<type></type>
有以下类别(可选设置如:<type>get</type>
)type 说明 get 获取当前域值。类似于 http get 方法 set 设置或替换 get 查询的值。类似于 http put 方法 result 说明成功的响应了先前的查询。类似于 http 状态码 200 error 查询和响应中出现的错误 -
下面是一个 IQ 例子:
2.7 XMPPPresence 类
-
这个类代表节点,我们通过此类提供的方法来生成 XML 数据。presence 它代表用户在线状态。
-
presence 用来表明用户的状态,如:online、offline、away、dnd (请勿打扰) 等。当改变自己的状态时,就会在 stream 的上下文中插入一个 Presence 元素,来表明自身的状态。要想接受 presence 消息,必须经过一个叫做 presence subscription 的授权过程。
-
<type></type>
有以下类别(可选设置如:<type>subscribe</type>
):type 说明 available 上线 unavailable 下线 away 离开 do not disturb 忙碌 subscribe 订阅其他用户的状态 probe 请求获取其他用户的状态 unavailable 不可用,离线(offline)状态 -
<show></show>
节点有以下类别,如<show>dnd</show>
:show 说明 chat 聊天中 away 暂时离开 xa eXtend Away,长时间离开 dnd 勿打扰 -
<status></status>
节点- 这个节点表示状态信息,内容比较自由,几乎可以是所有类型的内容。常用来表示用户当前心情,活动,听的歌曲,看的视频,所在的聊天室,访问的网页,玩的游戏等等。
-
<priority></priority>
节点- 范围 -128~127。高优先级的 resource 能接受发送到 bare JID 的消息,低优先级的 resource 不能。优先级为负数的 resource 不能收到发送到 bare JID 的消息。
-
发送一个用户在线状态的例子:
2.8 XMPPMessage 类
-
XMPPMessage 是 XMPP 框架给我们提供的,方便用于生成 XML 消息的数据。
-
message 是一种基本 推送 消息方法,它不要求响应。主要用于 IM、groupChat、alert 和 notification 之类的应用中。
-
<type></type>
有以下类别(可选设置如:<type>chat</type>
):type 说明 normal 类似于 email,主要特点是不要求响应 chat 类似于 qq 里的好友即时聊天,主要特点是实时通讯 groupchat 类似于聊天室里的群聊 headline 用于发送 alert 和 notification error 如果发送 message 出错,发现错误的实体会用这个类别来通知发送者出错了 -
<body></body>
节点- 所要发送的内容就放在 body 节点下
-
消息节点的例子:
3、XMPPFramework 框架使用
3.1 CocoaPods 导入框架
-
1、通过 CocoaPods 导入第三方框架 XMPPFramework。
-
在 Podfile 文件中加入如下代码,在终端中,使用命令
pod install
下载添加 XMPPFramework 框架。
-
-
2、在需要使用 XMPPFramework 的文件中导入以下头文件。
3.2 导入框架过程中问题解决
-
1、用 Cocoapods 集成 XMPPFramework 遇 Module 'KissXML' not found 等问题解决方法。
-
一般来说,通过 Coacopods 集成集成第三方框架,不会再有依赖库方面的问题,所以需要检查导入方式是否正确,最终找到原因,仔细看 githup 上导入说明
-
因此,Podfile 里必须写入这一句
-
-
2、Xcode8 之后 XMPP 重定义 Redefinition of module 'dnssd' 问题解决方法。
-
在升级 Xcode 到 8 之后,原来的关于 XMPP 的项目运行报错,错误信息为: Redefinition of module 'dnssd'。系统和XMPP框架同时用到了 'dnssd',大概就是错误的原因。
-
解决方案:
-
-
3、在 pod update 的过程中有的童鞋会遇到下面这样的错误。
-
这个是因为更新的 XMPP 框架中支持的最低版本为 iOS 8.0 / macOS 10.8。The minimum deployment target is iOS 8.0 / macOS 10.8.
-
把 Podfile 文件中
- 的 7.0 改为 8.0 或以上。
-
-
4、pod 更新完成了,出现下面这样的错误。
-
到报错的工程里面搜一下
- 改成相反的值就行了,别改没有报错的工程。
-
4、XMPPFramework 实现简单聊天
- 聊天实现的原理就是,一个客户端通过 XMPP 协议把信息传给服务器,服务器再发消息发给另一个客户端。
4.1 用户注册
-
初始化
-
与服务器建立链接
-
进行注册
4.2 用户登录、注销
-
初始化
-
与服务器建立链接
-
进行登录认证
-
与服务器断开链接,用户注销
-
用户登录信息本地化存储
- 添加第三方框架 SAMKeychain。
4.3 好友管理
-
初始化
-
获取好友列表
-
刷新好友列表
-
刷新好友状态
-
添加好友
-
收到添加好友申请
-
删除好友
4.4 文本消息管理
-
初始化
-
发送文本消息
-
接收文本消息
-
消息回执
-
这个是 XEP-0184 协议的内容。
-
发送消息时附加回执请求
-
收到回执请求的消息,发送回执
-
4.5 图片消息管理
-
图片和语音文件发送的基本思路:
- 先将图片/语音转化成二进制文件,然后将二进制文件进行 base64 编码,编码成字符串。在即将发送的 message 内添加一个子节点,节点的 stringValue(节点的值)设置这个编码后的字符串。
- 然后消息发出后取出消息文件的时候,通过 messageType 先判断是不是图片/语音信息,如果是图片/语音信息先通过自己之前设置的节点名称,把这个子节点的 stringValue 取出来,应该是一个 base64 之后的字符串。
-
选择图片
-
发送图片消息
- msgType 自定义消息类型,image:图片消息,audio:音频消息
-
接收图片消息
4.6 语音消息管理
-
图片和语音文件发送的基本思路:
- 先将图片/语音转化成二进制文件,然后将二进制文件进行 base64 编码,编码成字符串。在即将发送的 message 内添加一个子节点,节点的 stringValue(节点的值)设置这个编码后的字符串。
- 然后消息发出后取出消息文件的时候,通过 messageType 先判断是不是图片/语音信息,如果是图片/语音信息先通过自己之前设置的节点名称,把这个子节点的 stringValue 取出来,应该是一个 base64 之后的字符串。
-
录制/播放语音
-
发送语音消息
- msgType 自定义消息类型,image:图片消息,audio:音频消息
-
接收语音消息
4.7 心跳检测
-
为了监听服务器是否有效,增加心跳监听,用 XEP-0199 协议。
-
在 XMPPFrameWork 框架下,封装了 XMPPAutoPing 和 XMPPPing 两个类都可以使用,因为 XMPPAutoPing 已经组合进了 XMPPPing 类,所以 XMPPAutoPing 使用起来更方便。
-
初始化并启动 ping
-
停止 ping
4.8 自动重连
-
当意外与服务器断开连接,自动重新连接上去,并且将上一次的信息自动加上去。
-
初始化
5、XMPPFramework 快速登录
- 具体讲解链接
6、XMPPFramework 重连以及其他问题
- 具体讲解链接