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

前言

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

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

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

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

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

看图

  • 用户注册


    (十)即时通讯之XMPPFramework登陆注册_第1张图片
    注册.gif
  • 登陆


    (十)即时通讯之XMPPFramework登陆注册_第2张图片
    登陆
  • 切换用户登陆


    (十)即时通讯之XMPPFramework登陆注册_第3张图片
    切换用户登陆.gif
  • 注销


    (十)即时通讯之XMPPFramework登陆注册_第4张图片
    注销

今天讲的是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   : [email protected]
    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   : [email protected]
    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查阅

未完待续...

你可能感兴趣的:((十)即时通讯之XMPPFramework登陆注册)