XMPP实现简单的登录注册功能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/longshihua/article/details/51027197
XMPPFramework框架是通过代理的方式实现消息传递的,所以要实现注册登录功能,先理解一些基本的连接过程:

1.运行后需要和服务器建立一个长连接,系统会反馈连接是否成功

2.成功时需要告诉服务器的用户的密码,服务器判断是否给予授权

3.成功授权后,告诉服务器上线了。

4.将要离开时告诉服务器,我需要断开链接了。

5.服务器反馈你可以断开了,然后你再告诉服务器你下线了

用户登录的实现:

 1:实例化XMPPStream并设置代理,同时添加代理到工作队列
 2:使用JID连接至服务器,默认端口为5222,JID字符串中需要包含服务器的域名
 3:在完成连接的代理方法中验证用户密码,连接完成后XMPPStream的isConnect属性为YES
 4:在验证代理方法中判断用户是否登录成功
 5:上线或者下线成功后,向服务器发送Presence数据,以更新用户在服务器的状态

用户注册的实现:

1:与登录一样,首先发送帐号建立连接 
2:连接成功后,发送注册请求
3:注册成功后,会通知代理相应代理方法。
4:授权密码

下面来一步一步实现功能:

一:首先创建一个工程,命名为XMPPDemo

二:导入XMPPFramework框架

方法二种:

1:使用CocoaPods,不需要进行工程配置,可以直接使用!不会使用CocoaPods可以看该文章:http://code4app.com/article/cocoapods-install-usage导入XMPPFramework框架成功可以打开工程看到如下目录,工程中已经含有我们需要的框架:


2:  手动导入可以看该博客:http://www.cnblogs.com/dsxniubility/p/4307057.html

三:准备工作做好了,那么开始编写代码

1:首先在Main.storyboard中搭建一个简单的登录注册界面,运行效果如下:


2:下面来一起看一下实现代码

1)首先是自定义的管理类

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

#import <XMPP.h>


//block 用户登录,注册部分

typedef void (^OperationSuccessBlock)();

typedef void (^OperationfailedBlock)(NSString *error);


@interface SHXMPPManager : NSObject<XMPPStreamDelegate>


+(SHXMPPManager *)xmppManager;

@property(nonatomic,strong,readonly)XMPPStream *xmppStream;

//是否注册用户标示

@property (assign,nonatomic)BOOL isRegisterUser;

@property(nonatomic,copy)OperationSuccessBlock successBlock;

@property(nonatomic,copy)OperationfailedBlock failedBlock;


//初始化XMPPStream

-(void)setupStream;


//登录

-(void)loginWithUserName:(NSString *)userName password:(NSString *)password loginSuccess:(OperationSuccessBlock)loginSuceess loginFailed:(OperationfailedBlock)loginFailed;


//注册

- (void)registerWithUserName:(NSString *)userName  password:(NSString *)password registerSuccess:(OperationSuccessBlock)registerSuccess registerFailed:(OperationfailedBlock)registerFailed;


@end


#import "SHXMPPManager.h"


#define dispatch_main_sync_safe(block)\

if ([NSThread isMainThread]) {\

block();\

} else {\

dispatch_sync(dispatch_get_main_queue(), block);\

}


//本地服务器端口名

#define kxmppServer  @"longshihuademacbook-pro.local"


@interface SHXMPPManager (){


    NSString *_userName;   //用户名

    NSString *_password;   //密码

}


@end


@implementation SHXMPPManager


//创建一个单例模式来管理xmpp的连接和操作

+(SHXMPPManager *)xmppManager{


    static SHXMPPManager *manager =nil;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        manager = [[SHXMPPManager alloc]init];

    });

    

    return manager;

}


#pragma mark ----- 登录注册部分 -------


-(void)loginWithUserName:(NSString *)userName password:(NSString *)password loginSuccess:(OperationSuccessBlock)loginSuceess loginFailed:(OperationfailedBlock)loginFailed{

    

    [self initWithUserName:userNamepassword:passwordloginSuccess:loginSuceessloginFailed:loginFailed];

}


-(void)registerWithUserName:(NSString *)userName password:(NSString *)password registerSuccess:(OperationSuccessBlock)registerSuccess registerFailed:(OperationfailedBlock)registerFailed{


    self.isRegisterUser =YES;

    [self initWithUserName:userNamepassword:passwordloginSuccess:registerSuccessloginFailed:registerFailed];

}


-(void)initWithUserName:(NSString *)userName password:(NSString *)password loginSuccess:(OperationSuccessBlock)suceess loginFailed:(OperationfailedBlock)failed{


    self.successBlock = suceess;

    self.failedBlock = failed;

    _userName = userName;

    _password = password;

    

    [selfcurrentStateIsConnected];

    [self connect];

}


#pragma mark  ------- 建立连接相关代理 -----


//登录操作,也就是连接xmpp服务器,该方法会首先被调用。

-(void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket{

    NSLog(@"%@ %@",sender,socket);

}


//连接成功时调用,然后开始授权密码验证

-(void)xmppStreamDidConnect:(XMPPStream *)sender{

    

    if (self.isRegisterUser) {

        //用户注册,发送注册请求

        [self.xmppStreamregisterWithPassword:_passworderror:nil];

    } else {

        //用户登录,发送身份验证请求

        [self.xmppStreamauthenticateWithPassword:_passworderror:nil];

    }

}


//断开连接时调用.此方法在stream连接断开的时候调用,注意这些代理方法都是异步的.

-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{

    NSLog(@"断开连接! %@",sender);

}


#pragma mark --------  授权部分 ----------

//授权成功,开始发送信息

-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{


    __weak SHXMPPManager *weakSelf =self;

    dispatch_main_sync_safe(^{

        if (weakSelf.successBlock) {

            weakSelf.successBlock();

        }

    });

    //通知服务器用户上线

    [self goOnline];

}


//授权失败,该方法会被调用

-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{

    

       __weak SHXMPPManager *weakSelf =self;

        //根据是否是主线程再决定是否使用GCD

        dispatch_main_sync_safe(^{

          if (self.failedBlock) {

              weakSelf.failedBlock(error.description);

            }

        });

}


#pragma mark ------- 注册相关代理 ----------

-(void)xmppStreamDidRegister:(XMPPStream *)sender{


    self.isRegisterUser =NO;

    

    __weak SHXMPPManager *weakSelf =self;

    dispatch_main_sync_safe(^{

        if (weakSelf.successBlock) {

            weakSelf.successBlock();

        }

    });

}


-(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{

    

    __weak SHXMPPManager *weakSelf =self;

    dispatch_main_sync_safe(^{

        if (self.failedBlock) {

            weakSelf.failedBlock(error.description);

        }

    });

}


//链接服务端

-(void)connect{

    

    // 如果XMPPStream当前已经连接,直接返回

    if ([_xmppStreamisConnected]) {

        return;

    }

    

    // 设置XMPPStreamJID和主机.完整的Jid包括 Username@Domain/resource. Username:用户名,Domain登陆的XMPP服务器域名。Resource:资源/来源,用于区别客户端来源,xmpp协议设计为可多客户端同时登陆,resource就是用于区分同一用户不同端登陆。

    XMPPJID *myJID = [XMPPJIDjidWithString:[selfgetBareJidStr:_userName]];

    [_xmppStream setMyJID: myJID];

    [_xmppStream setHostName:kxmppServer];

    [_xmppStream setHostPort:5222];

    

    // 开始连接提示:如果没有指定JIDhostName,才会出错,其他都不出错。

    NSError *error = nil;

    NSLog(@"%d", [_xmppStreamconnectWithTimeout:XMPPStreamTimeoutNoneerror:&error]);

    if (error) {

        NSLog(@"连接请求发送出错 %@",error.localizedDescription);

    }else{

        NSLog(@"连接请求发送成功!");

    }

}


//与服务器断开连接

-(void)disconnect{

    

    //通知服务器下线

    [selfgoOffLine];

    //XMPPStream断开连接

    [_xmppStream disconnect];

}


//如果已经存在连接,先断开连接

-(void)currentStateIsConnected{

    

    if ([self.xmppStreamisConnected]){

        [self.xmppStreamdisconnect];

    }

}


//初始化 XMPPStream并设置代理:

-(void)setupStream{

    

    _xmppStream = [[XMPPStreamalloc]init];

    [_xmppStreamaddDelegate:selfdelegateQueue:dispatch_get_main_queue()];

}


//XMPPStream 上线

-(void)goOnline{


    // 实例化一个展现,上线的报告,默认类型为:available

    XMPPPresence *presence = [XMPPPresencepresence];

    // 发送Presence给服务器,服务器知道上线后,只需要通知我的好友,而无需通知我,因此,此方法没有回调

    [_xmppStream sendElement:presence];

}


//XMPPStream 离线

-(void)goOffLine{


    XMPPPresence *presence = [XMPPPresencepresenceWithType:@"unavailable"];

    [_xmppStream sendElement:presence];

    

}


//Bare,除去resource部分,包含Username@Domain

- (NSString *)getBareJidStr:(NSString *)jidStr{

    

    if ([jidStr hasSuffix:kxmppServer]) {

        return jidStr;

    }else{

        return [NSStringstringWithFormat:@"%@@%@",jidStr,kxmppServer];

    }

}


-(void)dealloc{


    _xmppStream = nil;

    [_xmppStreamremoveDelegate:self];

}


@end


2)视图控制器中进行功能测试,代码和效果如下:

#import "ViewController.h"

#import "SHXMPPManager.h"


@interface ViewController ()<UITextFieldDelegate>


@property (weak, nonatomic) IBOutletUITextField *userNameTextField;

@property (weak, nonatomic) IBOutletUITextField *passwordTextField;


@end


@implementation ViewController



- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    [[SHXMPPManagerxmppManager]setupStream];

    

}


- (IBAction)registerButton:(UIButton *)sender {

    

    if ([selfisInputUserNameAndPassword]) {

       

        [[SHXMPPManagerxmppManager]registerWithUserName:self.userNameTextField.textpassword:self.passwordTextField.textregisterSuccess:^{

            [selfalertViewWithString:@"注册成功!"];

        } registerFailed:^(NSString *error) {

            [selfalertViewWithString:@"注册失败!"];

        }];

    }

}



- (IBAction)loginButton:(UIButton *)sender {

    

    if ([selfisInputUserNameAndPassword]) {

        [[SHXMPPManagerxmppManager]loginWithUserName:self.userNameTextField.textpassword:self.passwordTextField.textloginSuccess:^{

            [selfalertViewWithString:@"登录成功!"];

        } loginFailed:^(NSString *error) {

            [selfalertViewWithString:@"登录失败!"];

        }];

    }

}


/**

 *

 * 用于判断是否输入了用户名和密码

 */

-(BOOL)isInputUserNameAndPassword{

    

    if(self.userNameTextField.text.length ==0){

        [selfalertViewWithString:@"请输入用户名"];

        return NO;

    }elseif(self.passwordTextField.text.length ==0){

        [selfalertViewWithString:@"请输入密码"];

        return NO;

    }


    return YES;

}


-(void)alertViewWithString:(NSString *)string{

    

    UIAlertView *alertView = [[UIAlertViewalloc]initWithTitle:string

                                                        message:string

                                                       delegate:nil

                                              cancelButtonTitle:@"Ok"

                                              otherButtonTitles:nil];

    [alertView show];

}


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{


    [self.userNameTextFieldendEditing:YES];

    [self.passwordTextFieldendEditing:YES];

    

}


@end


效果图:
                
                      

注册成功可以在openfire中查看用户信息:
         

以上代码下载地址:https://github.com/longshihua/XMPPDemo

    

没有更多推荐了,返回首页