(十)即时通讯之XMPPFramework登陆注册

前言

这也是本人第一次琢磨关于即时通讯方面的内容,结合网上查看的相关资料搭建出来的仿微信小demo,如有意见请多多指教

写了这么多,尼玛终于到正题了,前面9篇讲的都是基本概念及相关环境的搭建,这里列举一下:

  • Sokcet套接字的简介
  • 网络七层协议,TCP/UDP的概念
  • CocoaSocket的使用
  • XMPP协议的简介
  • XMPP通讯环境SQL的搭建
  • XMPP通讯环境服务器openfire的搭建
  • XMPP通讯环境客户端message,Aduim,Spark的搭建
  • XMPPFramework框架的导入及简单介绍

具体项目可以在githubWeiChat下载进行查看,如若各位看官老爷觉得还可以请点star

下面开始进入正题
XMPPFramework的使用

看图

  • 用户注册


    注册.gif
  • 登陆


    登陆
  • 切换用户登陆


    切换用户登陆.gif
  • 注销


    注销

今天讲的是XMPP的登陆注册部分,废话不多说:

1.登陆注册部分常用的对象

  • XMPPStream XMPP通道:负责XMPP信息的传输以及传输状态等
  • XMPPReconnect 自动连接

2.准备工作

1.创建一个单例类名为XMPPManager,负责XMPP相关管理工作,比如各类登陆注册模块的激活,实现都在这里进行处理.
2.创建一个单例类名为UserManager,负责用户的账号密码的管理以及获取用户信息等方面.

3.登录注册实现部分

3.1实现原理

这里阐述下实现原理,具体实现过程请参考下部分代码以及项目内容.

 1.导入XMPPStream,XMPPReonnect头文件
 2.激活XMPPStream,XMPPReconnect模块并设置代理
 3.登录的流程:
  xmpp的登录流程是,
  3.1 传递 JID , Host , Port 先连接上服务器 
  3.2连接成功了 再 发送密码到服务器 ,
  3.3授权成功 或者 授权失败.这就代表登陆成功或失败,成功了则跳到微信主界面

 4.注册的流程:
   4.1xmpp的注册流程是, 传递 JID , Host , Port 先连接上服务器 :
通过JID连接成功
连接成功则会自动调用XMPPStreamDelegatexmppStreamDidConnect 代理方法
然后在通过代理方法调用 XMPPStream的发送密码的方法authenticateWithPassword
   4.2连接成功了 再 发送注册密码到服务器 
   4.3注册成功 或者 失败,注册成功了跳到登陆界面,进行登陆

共同点:
不管你jid存不存在 都能连接到服务器。

不同点:
发送的是授权密码 还是 发送注册密码 就是决定你是登录还是注册.
5.在登陆注册页面进行调用方法并传递状态

注意:
1.连接到服务器后,对于是登陆还是注册的判断
2.登陆成功后需要发送一个在线状态消息,离线了需要发送离线状态消息
3.在UserManager中登陆用户信息和注册用户信息分清楚
4.XMPPStream代理方法执行的顺序先后
5.block对于登陆注册状态的提示
6.对于XMPP JID的理解,用户名@服务器地址.设备信息(可选)

详细请看demo
7.这个demo里登录名就是密码,不影响使用,请注意

3.2XMPPManager部分

3.2.1单例类
#pragma mark 创建XMPPManager单例类
singleton_m(manager)
3.2.2创建XMPPStream对象
// 登录注册什么的都是和服务器交互,所以我们用到的类就是XMPPStream
- (void)connect {
    if (!self.stream) {
        // 创建XMPPStream,只需要初始化一次,所以加判断
        self.stream = [[XMPPStream alloc] init];
        // 设置stream的域名和端口号
        self.stream.hostName = kHostName;
        self.stream.hostPort = kHostPort;
        // 添加代理 连接成功后调用传密码的方法
        [self.stream addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
// 连接服务器
- (void)connectToServer {
    // 判断是否连接成功过
    if (![self.stream isConnected]) {
        // 连接到服务器
        NSError *error;
        [self.stream connectWithTimeout:XMPPStreamTimeoutNone error:&error];
        if (error) {
            NSLog(@"%@",error);
        } else {
            // 连接成功则会自动调用XMPPStreamDelegatexmppStreamDidConnect 代理方法
            // 然后在通过代理方法调用 XMPPStream的发送密码的方法authenticateWithPassword
            NSLog(@"连接成功");
        }
    }
}
3.2.3 用户登陆,使用登陆JID用户名
- (void)xmppUserLogin:(UserSatateBlock)block {
    // block赋值给全局变量,在代理方法中调用block传递登陆信息
    self.block = block;
    
    // 不管登陆几次,每次登陆之前都要先把连接断开
    [self.stream disconnect];
    
    // 初始化XMPPPStream
    [self connect];
    
    /**
     *  因为在调用之前,在userDefault中存储的是登陆用户的名字
        所以在这里获取用户的名字
     */
    UserManager *user = [UserManager sharedmanager];
    [user readLoginInfo];
    // 设置XMPPStream的JID   : yoyu@127.0.0.1.iPhone
    self.stream.myJID = [XMPPJID jidWithUser:user.loginName domain:kHostName resource:@"iPhone"];
    
    // 通过读取UserDefault中的name连接服务器
    [self connectToServer];
}
3.2.4用户注册,使用注册JID用户名
- (void)xmppUserRegist:(UserSatateBlock)block {
    self.block = block;
    
    // 不管登陆几次,每次登陆之前都要先把连接断开
    [self.stream disconnect];
    
    // 初始化XMPPPStream
    [self connect];
    
    /**
     *  因为在调用之前,在userDefault中存储的是注册用户的名字
        所以在这里获取用户的名字
     */
    UserManager *user = [UserManager sharedmanager];
    [user readRegistInfo];
    // 设置XMPPStream的JID   : yoyu@127.0.0.1.iPhone
    self.stream.myJID = [XMPPJID jidWithUser:user.registName domain:kHostName resource:@"iPhone"];
    
    // 通过读取UserDefault中的name连接服务器
    [self connectToServer];
}
3.2.5用户注销
- (void)xmppUserLogout {
    // 发送离线状态
    [self sendOfflineMessage];
    
    // 断开连接
    [self.stream disconnect];
    
    // 跳转到登陆界面
    UIWindow *window = [[UIApplication sharedApplication].delegate window];
    UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"LoginAndRegist" bundle:nil];
    window.rootViewController = [storyBoard instantiateInitialViewController];
}
3.2.6XMPPStreamDelegate连接服务器状态
#pragma mark -- XMPPStreamDelegate
/**
 *  登录的流程:
    xmpp的登录流程是, 传递 JID , Host , Port 先连接上服务器 ,连接成功了 再 发送密码到服务器 ,授权成功 或者 授权失败
 
    注册的流程:
    xmpp的注册流程是, 传递 JID , Host , Port 先连接上服务器 ,连接成功了 再 发送注册密码到服务器 ,注册成功 或者 失败
 
    共同点:
    不管你jid存不存在 都能连接到服务器。
 
    不同点:
    发送的是授权密码 还是 发送注册密码 就是决定你是登录还是注册

 */
/**
    通过JID连接成功
 *  连接成功则会自动调用XMPPStreamDelegatexmppStreamDidConnect 代理方法
    然后在通过代理方法调用 XMPPStream的发送密码的方法authenticateWithPassword
 */
#pragma mark -- 连接成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
    NSLog(@"通过JID建立连接成功");
    /**
     *  发送密码进行授权登陆
        分登陆密码
        和注册密码
        需要判断
     */
    UserManager *user = [UserManager sharedmanager];
    //[user readUserInfo];
    NSError *error = nil;
    NSLog(@"%@",user.loginName);
    NSLog(@"---%@",user.registName);
    if (user.loginName) {
        // 发送登陆密码
        [self.stream authenticateWithPassword:user.loginPsw error:&error];
    } else {
        // 发送注册密码
        [self.stream registerWithPassword:user.registPsw error:&error];
    }
}

#pragma mark -- 连接失败,与服务器断开连接(例如网络原因)
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error {
    NSLog(@"通过JID建立连接失败,与服务器断开连接");
    if (self.block) {
        self.block(XMPPUserStateTypeOther);
    }
    
    // 发送通知:状态2表示连接服务器失败
    [[NSNotificationCenter defaultCenter] postNotificationName:kLoginStateNotification object:nil userInfo:@{@"state":@"3"}];
}
3.2.7XMPPStreamDelegate登陆
/**
 *  属于登陆方面
 */
#pragma mark -- 授权登陆成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
    NSLog(@"授权登陆成功");
    if (self.block) {
        self.block(XMPPUserStateTypeSuccess);
    }
    
    // 授权登陆成功后,跳转到主界面
    UIWindow *window = [[UIApplication sharedApplication].delegate window];
    UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    window.rootViewController = [storyBoard instantiateInitialViewController];
    
    // 同时要发送一个在线的信息
    [self sendOnlineMessage];
}

#pragma mark -- 授权登陆失败
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{
    NSLog(@"授权登陆失败");
    if (self.block) {
        self.block(XMPPUserStateTypeFaild);
   }
}
3.2.8XMPPStreamDelegate注册
/**
 *  属于注册方面
 */
#pragma mark -- 注册成功
- (void)xmppStreamDidRegister:(XMPPStream *)sender{
    NSLog(@"注册成功");
    if (self.block) {
        self.block(XMPPUserStateTypeSuccess);
    }
}

#pragma mark -- 注册失败
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(NSXMLElement *)error{
    NSLog(@"注册失败");
    if (self.block) {
        self.block(XMPPUserStateTypeFaild);
    }
}
3.2.7登陆状态发送
#pragma mark ******************************
#pragma mark - 登陆成功后,给服务器发送一个在线消息:上线了
/**
    presence表示用户状态
 
   presence 的状态:
        available 上线
        away 离开
        do not disturb 忙碌
        unavailable 下线
 */
- (void)sendOnlineMessage {
    /**
     *  关于用户的上线和下线,需要用到一个类XMPPPresence 类。这个类是XMPPElement的子类,主要用来管理某些信息的展现。首先要实例化一个对象,这其中会用到一个presenceWithType 方法,有两个选择@"unavailable"代表下线,@"available"代表上线,一般情况上线的时候后面就可以直接省略。
     */
    XMPPPresence *pre = [XMPPPresence presenceWithType:@"available"];
    // XMPPPresence *pre = [XMPPPresence presence];
    [self.stream sendElement:pre];
}

#pragma mark - 离线时,给服务器发送一个在线消息:下线了
- (void)sendOfflineMessage {
    XMPPPresence *pre = [XMPPPresence presenceWithType:@"unavailable"];
    [self.stream sendElement:pre];
}

3.3登陆注册页面
这个部分就不详细介绍了,可以进demo查阅

未完待续...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容