上帝说:要约炮!于是有了XMPP
一、导入XMPP框架
下载
XMPPFramework框架GitHub: XMPPFramework
导入依赖框架
CocoaLumberjack: 日志框架CocoaAsyncSocket: 底层网络框架
需要添加CFNetwork&Security框架依赖(XCode 6+ 无需导入)KissXML: XML解析框架
需要添加libxml2.dylib框架依赖
需要指定如下编译选项:
Other Linker Flags = -lxml2
Header Search Paths = /usr/include/libxml2libidn
导入一下文件夹
AuthenticationCategoriesCoreUtilities- 添加依赖:
libresolv.dylib
导入XMPP扩展框架
Extensions文件夹- 导入
Sample_XMPPFramework.h并更名为:XMPPFramework.h - 添加PCH文件:
Add New File->Other->PCH文件- 添加
#import<UIKit/UIKit.h>到PCH文件中 - 设置编译选项,
Build Settings->Precompile prefix Header选择Yes - 设置编译选项,
Build Settings->Prefix Header设置PCH文件名:“项目名/“PCH文件名”
二、登录 & 注销
实现用户登录的步骤如下:
1. 实例化XMPPStream并设置代理,同时添加代理到工作队列
2. 使用JID连接至服务器,默认端口为5222,JID字符串中需要包含服务器的域名
3. 在完成连接的代理方法中验证用户密码,连接完成后XMPPStream的isConnect属性为YES
4. 在验证代理方法中判断用户是否登录成功
5. 上线或者下线成功后,向服务器发送Presence数据,以更新用户在服务器的状态
各部分的实现代码如下:
初始化
XMPPStream并设置代理:-(void)setupXMPPStream{ _xmppStream = [[XMPPStream alloc] init]; // 设置代理
[_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
}
连接到服务器
-(void)connectToHost{
NSLog(@"开始连接到服务器");
if (!_xmppStream) {
[self setupXMPPStream];
} // 设置登录用户JID
//resource 标识用户登录的客户端 iphone android XMPPJID *myJID = [XMPPJID jidWithUser:@"aaa" domain:@"bourne-mbp.local" resource:@"iphone" ];
_xmppStream.myJID = myJID; // 设置服务器域名
_xmppStream.hostName = @"bourne-mbp.local";//不仅可以是域名,还可是IP地址 // 设置端口 如果服务器端口是5222,可以省略
_xmppStream.hostPort = 5222; // 连接
NSError *err = nil;
if(![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&err]){
NSLog(@"%@",err);
} }连接成功后发送密码验证
-(void)sendPwdToHost{
NSLog(@"再发送密码授权");
NSError *err = nil;
[_xmppStream authenticateWithPassword:@"123456" error:&err];
if (err) {
NSLog(@"%@",err);
}
}
授权成功后,发送
在线消息#pragma mark 授权成功后,发送"在线" 消息-(void)sendOnlineToHost{ NSLog(@"发送 在线 消息");
XMPPPresence *presence = [XMPPPresence presence];
NSLog(@"%@",presence); [_xmppStream sendElement:presence];
}
需要实现的几个代理方法
#pragma mark 与主机连接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender{
NSLog(@"与主机连接成功");
// 主机连接成功后,发送密码进行授权
[self sendPwdToHost];
}
#pragma mark 与主机断开连接
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{
// 如果有错误,代表连接失败 NSLog(@"与主机断开连接 %@",error);
}
#pragma mark 授权成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
NSLog(@"授权成功"); [self sendOnlineToHost];
}
#pragma mark 授权失败
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{
NSLog(@"授权失败 %@",error);
}
注销登录
- 发送
离线信息 - 断开连接
-(void)logout{
// 1." 发送 `离线` 消息"
XMPPPresence *offline = [XMPPPresence presenceWithType:@"unavailable"];
[_xmppStream sendElement:offline];
// 2. 与服务器断开连接
[_xmppStream disconnect];
}
三、注册
与登录一样,首先发送帐号建立连接
连接成功后,发送注册的密码
注册成功后,框架会通知代理
实现以下代理方法
- (void)xmppStreamDidRegister:(XMPPStream *)sender {
NSLog(@"注册成功");
if (_resultBlock) {
_resultBlock(BWXMPPLoginResultSuccessed);
}
}
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error {
if (_resultBlock) {
_resultBlock(BWXMPPLoginResultFailure);
}
}
四、用户信息
XMPP是面向模块的,每一个大的动能都属于某一个模块,需要使用时,就在头文件中将其暴露出来(原本是被注释了的)。
工作原理:
添加用户信息模块之后,
XMPPFramework框架会自动从服务器获取用户信息,并使用CoreData保存到本地的数据库中,使用XMPPvCardTempModule可以访问数据在
XMPPFramework.h中将以下的头文件前面的注释去掉:// 电子名片模块
#import "XMPPvCardTempModule.h"
#import "XMPPvCardCoreDataStorage.h" // 头像模块
#import "XMPPvCardAvatarModule.h"初始化模块
//添加电子名片模块
_vCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
_vCard = [[XMPPvCardTempModule alloc] initWithvCardStorage:_vCardStorage]; //激活
[_vCard activate:_xmppStream]; //添加头像模块
_avatar = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:_vCard];
[_avatar activate:_xmppStream];应用
//xmpp提供了一个方法,直接获取个人信息
XMPPvCardTemp *myVCard =[WCXMPPTool sharedWCXMPPTool].vCard.myvCardTemp; // 设置头像
if(myVCard.photo){
self.haedView.image = [UIImage imageWithData:myVCard.photo];
} // 设置昵称
self.nicknameLabel.text = myVCard.nickname;
五、好友
与用户信息模块相似,添加相应的好友花名册模块即可。
头文件
// 花名册模块
#import "XMPPRoster.h"
#import "XMPPRosterCoreDataStorage.h"初始化
// 添加花名册模块【获取好友列表】
_rosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
_roster = [[XMPPRoster alloc] initWithRosterStorage:_rosterStorage];
[_roster activate:_xmppStream];应用
//使用CoreData获取数据
// 1.上下文【关联到数据库XMPPRoster.sqlite】
NSManagedObjectContext *context = [WCXMPPTool sharedWCXMPPTool].rosterStorage.mainThreadManagedObjectContext; // 2.FetchRequest【查哪张表】
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"XMPPUserCoreDataStorageObject"]; // 3.设置过滤和排序
// 过滤当前登录用户的好友
NSString *jid = [WCUserInfo sharedWCUserInfo].jid;
NSPredicate *pre = [NSPredicate predicateWithFormat:@"streamBareJidStr = %@",jid];
request.predicate = pre; //排序
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"displayName" ascending:YES];
request.sortDescriptors = @[sort]; // 4.执行请求获取数据
_resultsContrl = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil]; _resultsContrl.delegate = self; NSError *err = nil;
[_resultsContrl performFetch:&err];
if (err) {
WCLog(@"%@",err);
}- 注意:使用
NSFetchedResultsController并设置代理,如果数据库的内容发生了变化,这个类会自动通知代理,就可以设置界面的数据,做到实时更新。
- 注意:使用
六、消息
头文件
- 注意:这几个头文件没在
XMPPFramework.h文件中,需要自己添加
// 消息模块
#import "XMPPMessageArchiving.h"
#import "XMPPMessageArchivingCoreDataStorage.h"- 注意:这几个头文件没在
初始化
// 添加聊天模块
_msgStorage = [[XMPPMessageArchivingCoreDataStorage alloc] init];
_msgArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:_msgStorage];
[_msgArchiving activate:_xmppStream];应用
// 上下文
NSManagedObjectContext *context = [WCXMPPTool sharedWCXMPPTool].msgStorage.mainThreadManagedObjectContext;
// 请求对象
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"XMPPMessageArchiving_Message_CoreDataObject"]; // 过滤、排序
// 1.当前登录用户的JID的消息
// 2.好友的Jid的消息
NSPredicate *pre = [NSPredicate predicateWithFormat:@"streamBareJidStr = %@ AND bareJidStr = %@",[WCUserInfo sharedWCUserInfo].jid,self.friendJid.bare];
NSLog(@"%@",pre);
request.predicate = pre; // 时间升序
NSSortDescriptor *timeSort = [NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:YES];
request.sortDescriptors = @[timeSort]; // 查询
_resultsContr = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil]; NSError *err = nil;
// 代理
_resultsContr.delegate = self; [_resultsContr performFetch:&err]; NSLog(@"%@",_resultsContr.fetchedObjects);
if (err) {
WCLog(@"%@",err);
}
七、文件传送(图片,音频)
原理分析
- 使用
base64将文件转化为字符串,然后再通过XMPPFramework传输。 - 先将文件上传到服务器,再将文件网址通过
XMPPFramework转输给好友,好友收到后再自行下载文件。
- 使用
难点解析
- 需要给
XMPPFramework的``数据体添加一个信息类型字段。
XMPPMessage *msg = [XMPPMessage messageWithType:@"chat" to:self.friendJid]; //text 纯文本
//image 图片
[msg addAttributeWithName:@"bodyType" stringValue:bodyType]; // 设置内容
[msg addBody:text];
NSLog(@"%@",msg);
[[WCXMPPTool sharedWCXMPPTool].xmppStream sendElement:msg];- 根据消息类型解析消息
```objc
XMPPMessageArchiving_Message_CoreDataObject *msg = _resultsContr.fetchedObjects[indexPath.row]; // 判断是图片还是纯文本
NSString *chatType = [msg.message attributeStringValueForName:@"bodyType"];
if ([chatType isEqualToString:@"image"]) {
//下图片显示
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:msg.body] placeholderImage:[UIImage imageNamed:@"DefaultProfileHead_qq"]];
cell.textLabel.text = nil;
} else if ([chatType isEqualToString:@"text"]){ //显示消息
if ([msg.outgoing boolValue]) {//自己发
cell.textLabel.text = msg.body;
}else{//别人发的
cell.textLabel.text = msg.body;
} cell.imageView.image = nil;
}- 需要给
```
声明:
以上内容转自:
http://www.jianshu.com/p/c7bbbad90639#
上帝说:要约炮!于是有了XMPP的更多相关文章
- 技术笔记:XMPP之openfire+spark+smack
在即时通信这个领域目前只找到一个XMPP协议,在其协议基础上还是有许多成熟的产品,而且是开源的.所以还是想在这个领域多多了解一下. XMPP协议:具体的概念我就不写了,毕竟这东西网上到处是.简单的说就 ...
- xmpp
xmpp学习 下载: Openfire 服务器:Openfire 4.0.2 客户端:Spark 2.7.7 安装 Openfire安装: 根据提示一直下一步,服务器域名设置为:localhost(p ...
- iOS XMPP 通信协议实现 图形化直观感受
第一次随笔,实在不知写点什么有用的东西,那就分享一下本人最近的研究所得吧! 是关于iOS-XMPP-通信协议的实现,具体代码比较复杂,三言两句也实在难表达清楚,网上已有很多关于iOS XMPP协议的讲 ...
- (转)C# XMPP客户端与openfire通信(Matrix Xmpp 授权破解教程)
FROM:http://www.cnblogs.com/crabo/p/CRACK_MATRIX_XMPP.html 如此著名的XMPP , 居然试过jabber-net, agsXmpp,matri ...
- XMPP iOS客户端实现三:登录、注册
1.创建一个单例模式来管理xmpp的连接和操作 +(XMPPManager *)share { static XMPPManager *_share=nil; static dispatch_once ...
- XMPP iOS客户端实现二:xcode项目配置
1.下载XMPPFramework,下载地址:https://github.com/robbiehanson/XMPPFramework 2.创建项目并将XMPP库引入: 3.添加需要的库文件: 4. ...
- Openfire/XMPP学习之——一个简单的Smack样例
昨天讲了Openfire的搭建和配置,今天来讲一下Smack.如果对如何搭建和配置Openfire的,可以参考Openfire/XMPP学习之——Openfire的安装.配置. Smack是一个开源, ...
- MAC下的XMPP环境搭建
实现即时通信有多种方式,下面讲的是Mac下使用XMPP来实现. XML Messages Presence Protocol 可扩展消息处理协议 简单讲就是基于XML语言的点对点即时通信协议 原理: ...
- XMPP开发环境配置
首先配置XMPP开发环境配置需要的软件 先安装xampp-osx-1.8.3-5-installer.dmg 安装成功后launchpad里会多出一个XAMPP(其他),点开里面的manager-os ...
随机推荐
- ACM_递推题目系列之一涂色问题(递推dp)
递推题目系列之一涂色问题 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有排成一行的n个方格,用红(Red).粉(Pink).绿 ...
- Android 性能优化(20)多核cpu入门:SMP Primer for Android
SMP Primer for Android 1.In this document Theory Memory consistency models Processor consistency CPU ...
- 转 js实践篇:例外处理Try{}catch(e){}
程序开发中,编程人员经常要面对的是如何编写代码来响应错误事件的发生,即例外处理(exception handlers).如果例外处理代码设计得周全,那么最终呈现给用户的就将是一个友好的界面.否则,就会 ...
- C# 自动批量导入图片到数据库中
using Model; using System; using System.Collections.Generic; using System.Data; using System.Data.Sq ...
- windows 中常用的 cmd 命令汇总
查看系统基本信息: cmd -> systeminfo 或 run -> dxdiag 查询主板出厂日期: cmd -> wmic bios get releasedate 关闭本地 ...
- Spring与Struts2集成开发
Struts2和Spring都是不错的开源框架,Spring与Struts2集成开发,把二者结合在一起使用,开发效果更佳,效率杠杠的.下面介绍一下如何将Spring与Struts2集成在一起开发.分七 ...
- canvas一周一练 -- canvas绘制中国银行标志(4)
运行效果: <!DOCTYPE html> <html> <head> </head> <body> <canvas id=" ...
- 【linux】 下根目录,家目录区别,以及普通用户到root用户的切换
一:家目录 一般普通用户,家目录是/home/用户名 root用户,家目录是/root root登录系统,执行如下命令进入root的家目录 cd /cd ~ 进入家目录后执行如下命令获取具体路径 pw ...
- 扩增子统计绘图1箱线图:Alpha多样性
绘制Alpha多样性线箱图 绘图和统计全部为R语言,建议复制代码,在Rstuido中运行,并设置工作目录为存储之前分析结果文件的result目录 # 运行前,请在Rstudio中菜单栏选择“Sessi ...
- 11Oracle Database 视图
Oracle Database 视图 视图语法 create [or replace] view <名字> as <select 语句> 视图用于简化查询,视图中实际存放的是一 ...