iOS中 XMPP即时通讯实现的主要步骤
这里只是列出实现的只要步骤,不是全部代码。
首先导入XMPPFramework,及相关配置,完成后开始。
创建一个XMPPHelper 类来管理要进行的操作。
XMPPHelper.h文件如下
typedef void(^loginSuccessBlock)(void);
typedef void(^loginFailBlock)(NSString *info);
typedef void(^fenchFridendList)(id result);
typedef void(^logoutSuccessBlock)(void);
typedef void(^registerSuccessBlock)(void);
typedef enum {
kTypeLogin,
kTypeRegister
}ConnectType;
#import <Foundation/Foundation.h>
#define kXMPPHosetName @"lala"
#define kXMPPHostAddress @"192.168.13.17"
#define kHostPort 5222 @interface XMPPHelper : NSObject
{ ConnectType _connectType; }
@property(nonatomic,strong)XMPPStream *stream;
@property(nonatomic,strong)XMPPRoster *roster;
@property(nonatomic,copy)NSString *username;
@property(nonatomic,copy)NSString *password; @property(nonatomic,copy)loginSuccessBlock loginSuccessBlock;
@property(nonatomic,copy)loginFailBlock loginFailBlock;
@property(nonatomic,copy)fenchFridendList fenchFriendList;
@property(nonatomic,copy)logoutSuccessBlock logoutSuccessBlock;
@property(nonatomic,copy)registerSuccessBlock registerSuccessblock; +(instancetype)shareInstance;
//登陆
-(void)login:(NSString *)username password:(NSString *)password loginSuccessBlock:(loginSuccessBlock)block loginFailBlock:(loginFailBlock)failBlcok;
//获取好友列表
-(void)loadFriendList:(fenchFridendList)fenchfriendList;
//发送消息
-(void)sendMessage:(NSString *)message toUser:(NSString *)jid;
//注销
-(void)logoutAction:(logoutSuccessBlock)block;
//注册
-(void)registerAction:(NSString *)username password:(NSString *)password registerSuccessBlock:(registerSuccessBlock)registerBlock; @end
XMPPHelper.m文件如下
#define kHostAddress @"192.168.13.12"
#define kHostName @"zy"
#define KHostPort 5222
#import "XMPPHelper.h"
#import "User.h" static XMPPHelper *helper = nil;
@interface XMPPHelper() <XMPPStreamDelegate>{
ConnectTyep _connectType;
}
@end
@implementation XMPPHelper //单例
+ (instancetype) shareInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
helper = [[XMPPHelper alloc] init];
[helper _stepXMPPHelper];
});
return helper;
} //初始化的操作
- (void) _stepXMPPHelper {
//初始化流对象.
self.stream = [[XMPPStream alloc] init];
//创建自动连接的对象,当意外断开的时候,可以进行自动连接.
XMPPReconnect *reConnect = [[XMPPReconnect alloc] init]; //初始化花名册对象(好友列表)
//存储方式.
XMPPRosterCoreDataStorage *storage = [[XMPPRosterCoreDataStorage alloc] init];
self.roster = [[XMPPRoster alloc] initWithRosterStorage:storage]; //建立对象之间的联系
//激活.
[reConnect activate:self.stream];
//激活,使用花名册对象.
[self.roster activate:self.stream]; //设置代理;
[self.stream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[self.roster addDelegate:self delegateQueue:dispatch_get_main_queue()]; //设置服务器的基本信息.
//服务器的地址
[self.stream setHostName:kHostAddress];
[self.stream setHostPort:KHostPort];
//端口号
} #pragma mark XMPP 对外公开方法
- (void) login:(NSString *)userName password:(NSString *)password loginSuccessBlock:(LoginSuccessBlock)block loginFailBlock:(LoginFailBlock)failBlock { _connectType = kTypeLogin; self.userName = userName;
self.password = password;
self.loginFailBlock = failBlock;
self.loginSuccessBlock = block;
//登录的流程.
if (![self connect]) {
//连接失败的时候 调用失败的block
if (self.loginFailBlock) {
self.loginFailBlock(@"网络错误");
}
}
}
//发起连接
- (BOOL) connect {
//设置用户的jid
NSString *jidString = [NSString stringWithFormat:@"%@@%@",self.userName,kHostName];
//创建了一个jid对象
XMPPJID *jid = [XMPPJID jidWithString:jidString];
[self.stream setMyJID:jid];
NSError *ERROR = nil;
return [self.stream connectWithTimeout: error:&ERROR];
}
//上线的方法
- (void) online {
//默认情况下 上线的状态
XMPPPresence *presence = [XMPPPresence presence];
[self.stream sendElement:presence];
} //下线的方法
- (void) outLine { XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];//unavailable 离线的意思
//发送离线状态
[self.stream sendElement:presence]; } //查询好友列表 /**
<iq from='guojing@wxhl' type='get' id='roster_1' to='域名'>
<query xmlns='jabber:iq:roster'/> <!-- iq 信息有多种,根据命名空间来区分-->
</iq> */
- (void) loadFriendList :(FentchFriendList) fentchFriendList { self.fentchFriendList = fentchFriendList;
//创建xml片段
//创建<iq></iq>
NSXMLElement *iqElement = [NSXMLElement elementWithName:@"iq"];
XMPPJID *jid = self.stream.myJID;
[iqElement addAttributeWithName:@"from" stringValue:[jid description]];
//jid.domain ---> 服务器的域名
[iqElement addAttributeWithName:@"to" stringValue:jid.domain];
[iqElement addAttributeWithName:@"type" stringValue:@"get"];
[iqElement addAttributeWithName:@"id" stringValue:@""]; //创建子节点
NSXMLElement *queryElement = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:roster"];
//给iq节点增加子节点.
[iqElement addChild:queryElement];
//发送请求(好友列表)
[self.stream sendElement:iqElement];
}
//发送消息
//发送消息的格式
/**
<message
to='huangrong@wxhl'
from='guojing@wxhl'
type='chat'
xml:lang='en'>
<body>有个bug帮我看下</body>
</message>
*/
- (void) sendMessage:(NSString *)message toUser:(NSString *) jid { //NIL
if (!message || [message isEqualToString:@""]) {
return;
} NSXMLElement *messageElement = [NSXMLElement elementWithName:@"message"]; [messageElement addAttributeWithName:@"to" stringValue:jid];
XMPPJID *myJid = self.stream.myJID;
[messageElement addAttributeWithName:@"from" stringValue:myJid.description]; [messageElement addAttributeWithName:@"type" stringValue:@"chat"]; [messageElement addAttributeWithName:@"xml:lang" stringValue:@"en"];
//<message></message>创建完毕
//创建子节点<body></body>
NSXMLElement *bodyElement = [NSXMLElement elementWithName:@"body" stringValue:message];
[messageElement addChild:bodyElement]; //发送消息
[self.stream sendElement:messageElement];
} //注销方法
- (void) logOutAction : (LogoutSuccessBlock) block {
//发送离线的消息
[self outLine]; //断开连接,主动断开链接
[self.stream disconnect]; if (block) {
block();
}
}
//注册的方法
- (void) registerUser:(NSString *)userName password:(NSString *)password registerSuccessBlock:(RegisterSuccessBlock) block {
_connectType = kTypeRegister;
//连接
self.userName = userName;
self.password = password;
self.registerBlock = block; [self connect];
} #pragma mark - XMPP DELEGAET
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
NSLog(@"连接成功");
//注册流程和登录流程都要使用该方法.在这里就要进行逻辑上判断
if (_connectType == kTypeRegister) {
[self.stream registerWithPassword:self.password error:nil];
}else if(_connectType == kTypeLogin){
//如果连接成功,则继续验证密码.
[self.stream authenticateWithPassword:self.password error:nil];
}
}
//验证成功的方法
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
NSLog(@"验证成功");
//要调用成功的block
//发送上线的状态.
[self online];
if (self.loginSuccessBlock) {
self.loginSuccessBlock();
}
}
//验证失败的方法
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error {
NSLog(@"验证失败");
//如果认证失败的话,要主动断开连接
[self.stream disconnect];
if (self.loginFailBlock) {
self.loginFailBlock(@"密码错误");
}
}
//获取查询信息
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {
/**
//根节点
<iq xmlns="jabber:client" type="result" id="123456" to="1234@zy/f54fcd02">
<query xmlns="jabber:iq:roster">
<item jid="gxb@localhost" name="" ask="subscribe" subscription="none">
<group>联系人列表</group>
</item>
<item jid="laoyan@zy" name="laoyan" subscription="both">
<group>12</group>
</item>
<item jid="deskmate@zy" name="deskmate" subscription="both">
<group>12</group>
<group>12</group>
</item>
<item jid="test123@zy" name="test123" subscription="both">
<group>联系人列表</group>
</item>
<item jid="zhengqingqing@192.168.13.12" name="" ask="subscribe" subscription="none">
<group>联系人列表</group>
</item>
<item jid="liuweiwei@zy" name="" subscription="both">
<group>让你变绿</group>
<group>让你变绿</group>
</item>
<item jid="zhengqingqing@zy" name="zhengqingqing" subscription="both">
<group>让你变绿</group>
</item>
<item jid="gxb1@zy" name="" subscription="both">
<group>联系人列表</group>
<group>联系人列表</group>
<group>变绿了</group>
</item>
<item jid="123456@localhost" name="" ask="subscribe" subscription="none">
<group>联系人列表</group>
</item>
</query>
</iq>
*/
//需要要类型是 字典
/**
dic = {
"联系人列表":[user1,user3],
"12":[user2]
}
*/
NSMutableDictionary *results = [NSMutableDictionary dictionary];
NSXMLElement *queryElement = iq.childElement;
//遍历Query节点
User *user = nil;
for (NSXMLElement *itemElement in queryElement.children) { user = [[User alloc] init]; NSString *jidString = [itemElement attributeStringValueForName:@"jid"]; user.jid = jidString; NSString *userName = [itemElement attributeStringValueForName:@"name"]; user.username = userName; for (NSXMLElement *groupElement in itemElement.children) {
//组名 12
NSString *groupString = groupElement.stringValue; NSMutableArray *users = results[groupString]; if (users == nil) {
users = [NSMutableArray array];
results[groupString] = users;
}
[users addObject:user];
}
} if (self.fentchFriendList) {
self.fentchFriendList(results);
} NSLog(@"获取好友列表 %@",results);
return YES;
}
//监听外部传过来的数据,就是如果有好友发来信息,则,回调此方法.
/**
//传过来很多message标签,我们只需要带body的message标签
<message xmlns="jabber:client" type="chat" id="purplea775e98a" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><composing xmlns="http://jabber.org/protocol/chatstates"/></message>
2015-11-18 09:35:20.264 WeChat[3162:161262] message is <message xmlns="jabber:client" type="chat" id="purplea775e98b" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><active xmlns="http://jabber.org/protocol/chatstates"/><body>sad</body></message>
2015-11-18 09:35:30.491 WeChat[3162:161262] message is <message xmlns="jabber:client" type="chat" id="purplea775e98c" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><active xmlns="http://jabber.org/protocol/chatstates"/></message>
*/
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
//判断当前的message标签是否带body子标签
if ([message isChatMessageWithBody]) {
NSString *body = message.body;
//获取发信息的人的jid
XMPPJID *jidFrom = message.from; NSDictionary *messageDic = @{
@"fromUser":jidFrom.description,
@"text":body
}; //通知,发出接收消息的通知
[[NSNotificationCenter defaultCenter] postNotificationName:kRecevieMessageNotification object:nil userInfo:messageDic]; } }
//注册成功调用的方法
- (void)xmppStreamDidRegister:(XMPPStream *)sender {
_connectType = kTypeLogin;
self.loginSuccessBlock = self.registerBlock;
self.registerBlock = nil;
[self xmppStreamDidConnect:sender];
} @end
把宏定义改成自己的参数,在相关的UI操作代码中创建 单例XMPPHelper 然后调用相关方法,并在相关的代理方法中实现必要的操作就可以了。
iOS中 XMPP即时通讯实现的主要步骤的更多相关文章
- iOS中XMPP简单聊天实现 好友和聊天
		
版权声明本文由陈怀哲首发自简书:http://www.jianshu.com/users/9f2e536b78fd/latest_articles;微信公众号:陈怀哲(chenhuaizhe2016) ...
 - XMPP即时通讯资料记录
		
几天开始研究XMPP即时通讯的技术,来实现移动应用的计时聊天功能.记录下参考的博客地址,还挺详细的. http://blog.csdn.net/fhbystudy/article/details/16 ...
 - iOS开发之XMPP即时通讯简单实现
		
首先搭载服务器和数据库 搭载服务器我用的是openfire,数据库用的是mysql 这里推荐两个链接 配置mysql,用的是mysql workbench http://justsee.iteye.c ...
 - xmpp即时通讯的笔记(摘抄)
		
xmpp的使用: 即时通讯 instant messaging(IM) : -->实时收发信息! 即时通讯相关软件: **QQ,MSN,GoogleTalk,AIM,Jabber(XMPP别名 ...
 - XMPP即时通讯
		
XMPP:XMPP是基于XML的点对点通讯协议,The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议). XMPP可用于服务类实时通讯,表 ...
 - iOS开发之即时通讯之Socket(AsyncSocket)
		
1.AsyncSocket介绍 如果需要在项目中像QQ微信一样做到即时通讯,必须使用socket通讯. iOS中Socket编程的方式: BSD Socket: BSD Socket 是UNIX系统中 ...
 - XMPP即时通讯基础知识
		
XMPP参考 一.定义 XMPP 是一种很类似于http协议的一种数据传输协议,它的过程就如同“解包装--〉包装”的过程,用户只需要明白它接受的类型,并理解它返回的类型,就可以很好的利用xmpp来进行 ...
 - XMPP即时通讯协议使用(前传)——协议详解
		
XMPP详解 XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议.在此基础上,XMPP ...
 - XMPP即时通讯协议使用(七)——利用Strophe实现WebIM及strophe.plugins插件使用
		
Strophe简介与Openfire配置 Strophe.js是为XMPP写的一个js类库.因为http协议本身不能实现持久连接,所以strophe利用BOSH模拟实现持久连接. 官方文档: http ...
 
随机推荐
- wampserver启动时图标不变绿的解决方法
			
有2种可能: 1.你安装wamp的时候安装路径中有中文,把路径全部改为英文. 2.其他软件占用了80端口号,解决方法是在服务中找微软的sql server或者其他服务,关掉服务后重启就行了.
 - C知识要点-个人总结
			
[数据结构]()C 结构体.C 共用体.C 数组.C 指针..... 存储类.auto.register.static.extern C 函数.定义函数.返回类型.函数名称.参数.函数主体.返回语句. ...
 - 小程序 页面到详情的id传递
			
比如电影列表页跳转到电影详情页 在movie.js获取movieId; processDoubanData: function (moviesDouban, settedKey, categoryTi ...
 - MySQL锁行锁表
			
select..for update; 给数据库表手动上锁 --锁行Begin; for update; --给 id=1 的行加上排它锁且 id 有索引 ; Commit; -- 锁表 BEGIN; ...
 - The eleventh day
			
What's the damage? Thanks so much for fixing the break on my car . What's the damage for the work yo ...
 - <Android开源库 ~ 1> GitHub Android Libraries Top 100 简介
			
转载自GitHub Android Libraries Top 100 简介 本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据 GitH ...
 - win10 mstsc 远程,登录失败,账号限制
			
问题: win7操作系统在局域网共享文件时,有时会遇到“登录失败:用户账户限制.可能的原因包括不允许空密码,登录时间限制,或强制的策略限制.”的情况,这要怎么解决呢 解决步骤: 1.按WIN+R,调出 ...
 - Mat转化为IplImage类型的方法
			
Mat image_mat; IplImage imgTmp = image_mat; IplImage *img = cvCloneImage(&imgTmp);
 - 然之协同系统3.5(OA+CRM+CASH+TEAM)
			
平台: Ubuntu 类型: 虚拟机镜像 软件包: mariadb-server 10.0.25 nginx 1.10.0 php7.0.4 collaboration commercial crm ...
 - java研发常见问题总结2
			
1. String.StringBuffer与StringBuilder之间区别 关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺点,到底什么时候该用谁呢?下面我们从以下几点说明一下 ...