XMPP实现好友注册,登陆,收发消息

XMPP消息格式
XMPP发送消息
Presence元素XML形式
IQ的XML形式
Message元素
登陆注册流程图

XMPPManager.h

#import <Foundation/Foundation.h>
#import "XMPPFramework.h"
//宏定义通知名
#define kRecieveMessageNotification @"RecieveMessageNotification"
//定义登陆成功失败block
typedef void(^LoginSuccessBlock)(void);
typedef void(^LoginFailBlock)(NSString *);
//定义注册成功失败block
typedef void(^RegisterSuccessBlock)(void);
typedef void(^RegisterFailBlock)(NSString *);

typedef void(^FriendsListBlock)(id result);

//宏定义主机名 IP 端口号
#define KHostName @"ljp"
#define KHostIP @"192.168.0.140"
#define KHostPort 5222

@interface XMPPManager : NSObject

+ (instancetype)shareManager;

//登录
- (void)loginWithUsername:(NSString *)username password:(NSString *)password successBlock:(LoginSuccessBlock)successBlock failBlock:(LoginFailBlock)failBlock;
//注册
- (void)registerWithUsername:(NSString *)username password:(NSString *)password successBlock:(RegisterSuccessBlock)successBlock failBlock:(RegisterFailBlock)failBlock;
//下线
- (void)goOffline;


//设置好友列表
- (void)setFriendsListBlock:(FriendsListBlock)block;

//发送消息
- (void)sendMessage:(NSString *)text toUser:(NSString *)jid;

@end

XMPPManager.m

#import "XMPPManager.h"
#import "XMPPFramework.h"
#import "User.h"

//枚举连接类型
typedef enum{

    XMPPConnectLogin,
    XMPPConnectRegister
}XMPPConnectType;

@interface XMPPManager ()<XMPPStreamDelegate, XMPPRosterDelegate>
{
    XMPPStream *_xmppStrem;
    XMPPRoster *_xmppRoster;

    NSString *_username;
    NSString *_password;

    LoginSuccessBlock _loginSusseccBlock;
    LoginFailBlock _loginFailBlock;
    RegisterSuccessBlock _registerSuccessBlock;
    RegisterFailBlock _registerFailBlock;

    FriendsListBlock _friendsListBlock;

    XMPPConnectType _xmppConnectType;
}

@end

@implementation XMPPManager

单例实现,并且生成XMPP管理对象

//自定义XMMP管理对象
+ (instancetype)shareManager {

    static XMPPManager *manager = nil;

    if (manager == nil) {

        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{

            manager = [[super allocWithZone:nil] init];
            [manager setupXMPPManager];
        });
    }
    return manager;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {

    return [self shareManager];
}

- (instancetype)copy {

    return self;
}
//自定义XMMP管理对象
- (void)setupXMPPManager {

    //1 创建数据流对象
    _xmppStrem = [[XMPPStream alloc] init];
    //2 设置重链接对象
    XMPPReconnect *reconnect = [[XMPPReconnect alloc] init];
    //绑定重链接对象到strem
    [reconnect activate:_xmppStrem];
    //3 创建花名册对象(好友列表)
    //XMPPRosterCoreDataStorage 花名册存储对象
    XMPPRosterCoreDataStorage *rcds = [[XMPPRosterCoreDataStorage alloc] init];
    _xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:rcds];
    //绑定花名册对象到strem
    [_xmppRoster activate:_xmppStrem];
    //4 设置主机名和端口号
    [_xmppStrem setHostName:KHostName];
    [_xmppStrem setHostPort:KHostPort];
    //5 设置代理对象
    [_xmppStrem addDelegate:self delegateQueue:dispatch_get_main_queue()];
    [_xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
}

登陆注册

连接
#pragma mark - 连接
- (BOOL)connect {

    //拼接JID
    NSString *jidString = [NSString stringWithFormat:@"%@@%@", _username, KHostName];
    //设置JID
    XMPPJID *jid = [XMPPJID jidWithString:jidString];
    //开连接
    _xmppStrem.myJID = jid;
    //开始连接服务器,返回连接状态
    XMPPStreamTimeoutNone永不超时
    return [_xmppStrem connectWithTimeout:XMPPStreamTimeoutNone error:nil];
}
连接成功
//连接成功以后调用
- (void)xmppStreamDidConnect:(XMPPStream *)sender {

    //判断连接类型是登陆还是注册
    if (_xmppConnectType == XMPPConnectLogin) {

        [_xmppStrem authenticateWithPassword:_password error:nil];
    }else if (_xmppConnectType == XMPPConnectRegister)
        [_xmppStrem registerWithPassword:_password error:nil];
}
注册
//注册成功,自动登录
- (void)xmppStreamDidRegister:(XMPPStream *)sender {

    //转换block类型
    _loginSusseccBlock = _registerSuccessBlock;
    //登录认证
    [_xmppStrem authenticateWithPassword:_password error:nil];
}
//注册失败
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error {

    if (_registerFailBlock) {

        _registerFailBlock(@"此账户已存在");
    }
    //断开连接,不断开连接接下来的服务器连接均会失败
    [_xmppStrem disconnect];
}
登陆
//密码认证成功
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {

    if (_loginSusseccBlock) {

        _loginSusseccBlock();
    }
    //上线
    [self goOnline];
}
//密码认证失败
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error {

    [_xmppStrem disconnect];
    if (_loginFailBlock) {

        _loginFailBlock(@"帐号密码错误");
    }
}

XMPP元素

状态(Presence): 上线下线
使用框架提供的元素发送
#pragma mark - 上线
- (void)goOnline {

    XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];
    [_xmppStrem sendElement:presence];
}
#pragma mark - 下线
- (void)goOffline {

    XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
    [_xmppStrem sendElement:presence];
    //下线必须断开服务器连接
    [_xmppStrem disconnect];
}
IQ(info/query): 好友列表
通过构建XML文件发送

查询好友列表

- (void)setFriendsListBlock:(FriendsListBlock)block {

    //保存block
    _friendsListBlock = [block copy];
    //创建IQ请求
    NSXMLElement *iq = [NSXMLElement elementWithName:@"iq"];
    //设置iq请求的三个属性
    XMPPJID *jid = _xmppStrem.myJID;
    [iq addAttributeWithName:@"from" stringValue:jid.description];
    [iq addAttributeWithName:@"type" stringValue:@"get"];
    [iq addAttributeWithName:@"id" stringValue:@"roster_1"];
    //设置iq请求的子元素
    XMPPElement *query = [XMPPElement elementWithName:@"query"];
    [query addAttributeWithName:@"xmlns" stringValue:@"jabber:iq:roster"];
    [iq addChild:query];
    //发送查询请求
    [_xmppStrem sendElement:iq];
}

收到查询回传 自动调用

- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {
    //判断iq的元素ID是否为传入的元素ID
    if ([iq.elementID isEqualToString:@"roster_1"]) {

        NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
        //获取query结点
        NSXMLElement *query = [iq elementForName:@"query"];
        for (NSXMLElement *item in query.children) {

            User *user = [[User alloc] init];
            //设置好友的JID名字和自定义名
            user.jid = [item attributeStringValueForName:@"jid"];
            user.username = [item attributeStringValueForName:@"name"];

            for (NSXMLElement *group in item.children) {
                //获取组名
                NSString *groupName = [group stringValue];
                //获取好友分组
                NSMutableArray *groupArray = dic[groupName];
                if (groupArray == nil) {
                    //若没有该好友分组,则创建
                    groupArray = [[NSMutableArray alloc] init];
                    [dic setObject:groupArray forKey:groupName];
                }
                //好友分组添加用户
                [groupArray addObject:user];
            }
        }
        //每一次for循环都把好友分组情况通过block传递出去
        if (_friendsListBlock) {

            _friendsListBlock([dic copy]);
        }
    }
    return YES;
}
消息(message)
发送消息
通过系统提供的元素发送消息
- (void)sendMessage:(NSString *)text toUser:(NSString *)jid {
    //如果消息或者发给对象为空,则返回
    if (text == nil || text.length == 0 || jid == nil || jid.length == 0) {
        return;
    }
    //如果发给对象不含服务器域名@wxhl
    NSRange range = [jid rangeOfString:[NSString stringWithFormat:@"@%@", KHostName]];
    if (range.location == NSNotFound) {
        return;
    }
    XMPPJID *toJID = [XMPPJID jidWithString:jid];
    //创建框架提供的信息元素
    XMPPMessage *message = [[XMPPMessage alloc] initWithType:@"chat" to:toJID];

    [message addBody:text];
    //发送元素
    [_xmppStrem sendElement:message];

}
通过构建xml发送消息
- (void)sendMessage:(NSString *)text toUser:(NSString *)jid {

    //判断传入参数是否为空
    if (text == nil || text.length == 0 || jid == nil || jid.length == 0) {
        return;
    }
    //jid格式检查 查找jid中是否包含了 @wxhl
    NSRange range = [jid rangeOfString:[NSString stringWithFormat:@"@%@", kHostName]];
    if (range.location == NSNotFound) {
        return;
    }

    //创建msg节点
    NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
    //添加属性
    XMPPJID *myJID = _xmppStream.myJID;
    [message addAttributeWithName:@"from" stringValue:myJID.description];
    [message addAttributeWithName:@"to" stringValue:jid];
    [message addAttributeWithName:@"type" stringValue:@"chat"];

    NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
    body.stringValue = text;
    //添加子节点
    [message addChild:body];

    //发送消息
    [_xmppStream sendElement:message];
}
接收消息
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
    //判断消息是否是有效信息
    if (message.isChatMessage) {
        //保存消息的内容和用户
        NSString *body = message.body;
        NSString *fromUserName = message.from.user;
        //将消息封装成通知的参数
        NSDictionary *info = @{@"user" : fromUserName,
                               @"body" : body
                               };
        //通过发送通知发送收到的消息
        [[NSNotificationCenter defaultCenter] postNotificationName:kRecieveMessageNotification object:nil userInfo:info];
    }

}
发出收到消息的回调
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message {

    NSLog(@"消息发送成功");
}
- (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error {

    NSLog(@"消息发送失败");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值