XMPP介绍与用法

示例代码地址

介绍

XMPP(前身是Jabber)是一种即时通讯协议,是一种分散型通讯网络,核心是基于XML流(传输过程中是二进制流,面向开发是XML流)传输数据,没有二进制传输。
扩展协议——Jingle,支持语音和视频,iOS平台尚不支持(可使用链接实现)。
XMPP是典型的C/S架构,定义了客户端,服务器,网关三个角色,通讯可在任意两者之间相互发生。这种架构服务端压力较大。基本的网络形式是基于socket,单客户端通过TCP/IP连接到服务器,在此之上传输XML流。
任何基于XMPP协议的服务器,是可以相互通讯的。

核心概念

  • XMPPStream:开发中最主要交互的类,所有扩展和自定义代码都要通过这个类进行
  • XMPPParser:供XMPP解析使用
  • XMPPJID:提供一个不可变JID的实现 ,遵守NSCoping协议和NSCoding协议
  • XMPPElement:
    • XMPPQ 请求
    • XMPPMessage 消息
    • XMPPPresence 出席
  • XMPPModule:开发XMPP扩展时使用
  • XMPPLogging:XMPP日志框架
  • XMPPInternal:整个XMPP框架内部使用的核心和高级底层内容

核心处理流程

  1. 在AppDelegate中,实现登录
  2. 初始化XMPPStream
  3. 连接服务器 [传一个JID]
  4. 连接服务器成功后,发送密码授权
  5. 授权成功后,发送 “在线(presence)” 消息
- (void)setupXMPPStream;
- (void)connectToHost;
- (void)sendPwdToHost;
- (void)sendOnlineToHost;

初始化

	_xmppStream = XMPPStream.alloc.init;
	// 如果需要添加扩展模块(名片、头像等),要在设置代理之前写
	[_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];

JID

XMPPJID *myJID = [XMPP jidWithUser:@"user" domain:@"text.local" resource:@"iphone"];

_xmppStream.myJID = myJID;
// 可以是域名或IP地址
_xmppStream.hostName = @"www.abc.com";
// 框架,默认端口是5222,可省略
_xmppStream.hostPort = 5222;

NSError*err = nil;
if (![_xmppstream connectWithTimeout:XMPPStreamTimeOutNone error:&err]) {

}

登录

- (void)sendOnlineToHost
{
    //  4. 授权成功后,发送“在线”消息
    XMPPPresence *presence = [XMPPPresence presence];
    // 发送XML类型presense字符串
    [_xmppStream sendElement:presence];
}

登出

- (void)loginout {
	// 创建消息对象,类型为离线
	XMPPresence *offline = [XMPPresence presenceWithType:@"unavailable"];
	// xmppStream发送离线消息
	[_xmppStream sendElement:offline];
	// 与服务器断开连接
	[_xmppStream disconnect];
}

常见模块

模块需在XMPPFramework.h头文件中导入。

// 自动连接模块
#import "XMPPReconnect.h"

// 电子名片模块
#import "XMPPvCardTempModule.h"
#import "XMPPvCardCoreDataStorage.h"

// 头像模块
#import "XMPPCardAvatarModule.h"

// 花名册模块
#import "XMPPRoster.h"
#import "XMPPRosterCoreDataStorage.h"

// 聊天(消息)模块
#import "XMPPMessageArchiving.h"
#import "XMPPMessageArchivingCoreDataStorage.h"

每一个模块添加后都要激活!

电子名片模块

  • XEP-0054提供一种机制,通过XMPP发送电子名片
  • 在XMPPFramework.h中启动电子名片扩展头文件:
#import "XMPPvCardCoreDataStorage.h"
#import "XMPPvCardTempModule.h"
  • 定义属性及成员变量
  • 为XMPPSteam添加电子名片扩展
  • 在需要时使用电子名片
// 添加电子名片模块
_vCard = [[XMPPvCardTempModule alloc] initWithvCardStorage:_vCardStorage];
[_vCard activate:_xmppStream];

头像模块

  • 在XMPPFramework.h中启动电子名片扩展头文件:
    #import "XMPPvCardAvatarModule.h"
    
  • 初始化
    _avatar = [[XMPPvCardAvatarModule alloc] initWithCardTempModule:_vCard];
    // 激活
    [_avatar activate:_xmppStream];
    
  • 使用
	XMPPvCardTemp *vCard = WCXMPPTool.sharedWCXMPPTool.vCard.myvCardTemp;
	vCard.photo = UIImagePNGRepresentation(image);
	// 更新,这个方法内部实现数据上传到服务器,无需程序自己操作
	[WCXMPPTool.sharedWCXMPPTool.vCard updateMyvCardTemp:vCard];
	```	
#### 当前用户个人信息获取
- 使用coreData获取数据
- 上下文关联到数据
- FetchRequest
- 设置过滤和排序
- 执行请求获取数据
```js
// XMPP提供直接过去个人信息的API
XMPPvCardTemp *myvCard = WCXMPPToll.sharedWCXMPPTool.vCard.myVCardTemp;
// 设置头像
if (myCard.photo) {
	// 设置头像的业务代码
	headImgV.image = myCard.photo
}
// 设置昵称
nicklabel.text = myCard.nickname;
// 设置微信号(用户名)
NSString *user = WCUserInfo.sharedWCUserInfo.user;
userlabel.text = user;

自动连接模块

_reconnect = XMPPReconnect.alloc.init;
[_reconnect activate:_xmppStream];

花名册模块

  • 需要使用花名册,首先在XMPPFramework.h中启用电子名片扩展头文件:
#import "XMPPRoster.h"
#import "XMPPRosterCoreDataStorage.h"
  • 定义属性与成员变量
  • 为XMPPStream添加花名册扩展
  • 设置花名册代理
_rosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
_roster = [[XMPPRoster alloc] initWithRosterStorage:_rosterStorage];
// 激活
[_roster activate:_xmppStream];
  • 在需要时使用花名册
// 创建上下文
NSManageObjectContext *context = WCXMPPTool.sharedWCXMPPTool.rosterStorage.mainThreadManagedObjectContext;
// 查询哪张表
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:"XMPPUserCoreDataStorageObject"];
// 设置过滤和排序,过滤当前登录用户的好友
NSString *jid = WCUserInfo.sharedWCUserInfo.jid;
NSPrediate *pre = [NSPrediate predicateWithFormat:@"streamBareJidStr = %@", jid];
request.predicate = pre;
// 排序
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"displayName" ascending:YES];
request.sortDescriptors = @[sort];
// 执行请求获取数据,好友列表
self.friends = [context executeFetchRequest:request error:nil];
// resultsContrl = [[NSFetchedResultsController alloc] initWithFetchRequest:request manageObjectContext:context sectionNameKeyPath:nil cacheName:nil];
// resultsContrl.delegate= self;
// NSError *err = nil;
// [resultsContrl performFetch:&err];
// if (err)  return;
// delegate
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
	// 数据发生改变后的回调
}
好友信息
// cell 代理方法中获取好友信息
XMPPUserCoreDataStorageObject *friend = _resultsContrl.fetchedObjects[indexPath.row];
// 获取好友状态,0表示在线,1表示离开,2表示离线
friend.sectionNum.intValue
添加好友
// 是否为添加自己
if ([user isEqualToString:WCUserInfo.sharedWCUserInfo.user])  return;

NSString *jidStr = [NSString stringWithFormat:@"%@@%@", user, domain];
XMPPJID*friendJid = [XMPPJID jidWithString:jidStr];

// 判断好友是否存在
if ([WCXMPPTool.sharedWCXMPPTool.rosterStorage userExistsWithJID:friendJid xmppStream:WCXMPPTool.sharedWCXMPPTool.xmppStream]) return;
// 添加好友,使用XMPP订阅API
[WCXMPPTool.sharedWCXMPPTool.roster subscribePresenceToUser:friendJid];
删除好友
XMPPUserCoreDataStorageObject *friend = _resultsContrl.fetchedObjects[indexPath.row];
XMPPJID *jid = friend.jid;
[WCXMPPTool.sharedWCXMPPTool.roster removeUser:jid];

聊天模块

  • 初始化
_msgStorage = [[XMPPMessageArchivingCoreDataStorage alloc] init];
_msgArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:_msgStorage];
[_msgArchiving activate:_xmppStream];
  • 发送聊天消息
- (void)sendMsgWithText:(NSString *)text bodyType:(XMPPBodyType)type {
	
	XMPPMessage *msg = [XMPPMessage messageWithType:@"chat" to:_friendJid];
	switch (type) {
		case XMPPBodyTypeText:
        {
            [message addAttributeWithName:@"bodyType" stringValue:@"text"];
        }
            break;
        case XMPPBodyTypeImage:
        {
            [msg addAttributeWithName:@"bodyType" stringValue:@"image"];
        }
            break;
        case XMPPBodyTypeVideo:
        {
            [msg addAttributeWithName:@"bodyType" stringValue:@"video"];
        }
            break;
        default:
            break;
    }
	[msg addBody:text];
	[WCXMPPTool.sharedWCXMPPTool.xmppStream sendElement:msg];
}

释放XMPPStream相关资源

- (void)teardowmStream {
	[xmppStream removeDelegate:self];
	[xmppRoster removeDelegate:self];
	
	[xmppReconnect deactivate];
	[xmppRoster deactivate];
	
	[xmppCardTempModule deactivate];
	[xmppCardAvatarModule deactivate];
	[xmppCapabilities deactivate];
	[xmppStream disconnect];
	
	xmppReconnect = nil;
	xmppStream = nil;
	xmppRoster = nil;
	xmppCardAvatarModule = nil;
	xmppCardTempModule = nil;
	xmppCapabilities = nil;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值