zoukankan      html  css  js  c++  java
  • XMPP系列(二)----用户注册和用户登录功能

    1.创建一个新工程



    2.导入XMPP框架

    最新的XMPP框架下载地址:https://github.com/robbiehanson/XMPPFramework

    将XMPP的几个文件夹拖进工程中,需要的文件如下:


    然后把Sample_XMPPFramework.h改名为XMPPFramework.h

    接下来导入两个依赖库:libresolv.dylib和libxml2.dylib,然后添加header search:


    再添加一个pch文件


    在pch文件中添加如下代码:

    #ifdef __OBJC__
        #import <UIKit/UIKit.h>
    
        #import "XMPPFramework.h"
    #endif
    再然后设置工程的pch文件



    $SRCROOT后面是项目名/pch文件名。

    做完以上步骤,项目就可以编译成功啦!

    现在开始搭建项目的登录界面:

    首先封装一个XMPP工具类:JKXMPPTool

    .h文件

    #import <Foundation/Foundation.h>
    
    @interface JKXMPPTool : NSObject<XMPPStreamDelegate>
    
    @property (nonatomic, strong) XMPPStream *xmppStream;
    // 模块
    @property (nonatomic, strong) XMPPAutoPing *xmppAutoPing;
    @property (nonatomic, strong) XMPPReconnect *xmppReconnect;
    
    @property (nonatomic, assign) BOOL  xmppNeedRegister;
    @property (nonatomic, copy)   NSString *myPassword;
    
    + (instancetype)sharedInstance;
    - (void)loginWithJID:(XMPPJID *)JID andPassword:(NSString *)password;
    - (void)registerWithJID:(XMPPJID *)JID andPassword:(NSString *)password;
    
    @end
    .m文件

    #import "JKXMPPTool.h"
    
    @implementation JKXMPPTool
    
    static JKXMPPTool *_instance;
    + (instancetype)sharedInstance
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [JKXMPPTool new];
        });
        
        return _instance;
    }
    
    - (XMPPStream *)xmppStream
    {
        if (!_xmppStream) {
            _xmppStream = [[XMPPStream alloc] init];
            
            //socket 连接的时候 要知道host port 然后connect
            [self.xmppStream setHostName:kXMPP_HOST];
            [self.xmppStream setHostPort:kXMPP_PORT];
            //为什么是addDelegate? 因为xmppFramework 大量使用了多播代理multicast-delegate ,代理一般是1对1的,但是这个多播代理是一对多得,而且可以在任意时候添加或者删除
            [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
         
        }
        return _xmppStream;
    }
    
    - (void)loginWithJID:(XMPPJID *)JID andPassword:(NSString *)password
    {
        // 1.建立TCP连接
        // 2.把我自己的jid与这个TCP连接绑定起来(即使匿名登录,依然得设置JID,只是我们可以设置一个任意的JID,例如<span style="font-family: Arial, Helvetica, sans-serif;">anonymous@<domain></span>)
        // 3.认证(登录:验证jid与密码是否正确,加密方式 不可能以明文发送)--(出席:怎样告诉服务器我上线,以及我得上线状态
        //这句话会在xmppStream以后发送XML的时候加上 <message from="JID">
        [self.xmppStream setMyJID:JID];
        self.myPassword = password;
        self.xmppNeedRegister = NO;
        [self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:nil];
    }
    
    //注册方法里没有调用auth方法
    - (void)registerWithJID:(XMPPJID *)JID andPassword:(NSString *)password
    {
        [self.xmppStream setMyJID:JID];
        self.myPassword = password;
        self.xmppNeedRegister = YES;
        [self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:nil];
    }
    
    - (void)goOnline
    {
        // 发送一个<presence/> 默认值avaliable 在线 是指服务器收到空的presence 会认为是这个
        XMPPPresence *presence = [XMPPPresence presence];
        
        //发送复杂一点的出席状态
        //<presence type="avaliable">
        //        <status>我很忙</status>
        //        <show>xa</show>
        //    </presence>
        [presence addChild:[DDXMLNode elementWithName:@"status" stringValue:@"我现在很忙"]];
        [presence addChild:[DDXMLNode elementWithName:@"show" stringValue:@"xa"]];
        
        [self.xmppStream sendElement:presence];
    }
    
    #pragma mark ===== XMPPStream delegate =======
    //socket 连接建立成功
    - (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket
    {
        NSLog(@"%s",__func__);
    }
    
    //这个是xml流初始化成功
    - (void)xmppStreamDidConnect:(XMPPStream *)sender
    {
        NSLog(@"%s",__func__);
        //匿名登录 会随机生成一个username和JID,这个是在服务器的内存中随机生成,不会写入服务器的数据表,例如生成的jid为<p class="p1"><span class="s1">1nv8l4khxg@im.joker.cn/1nv8l4khxg</span></p>
        //为了防止客户端匿名登录,服务器有策略关闭匿名
        //    [self.xmppStream authenticateAnonymously:nil];
        if (self.xmppNeedRegister) {
            [self.xmppStream registerWithPassword:self.myPassword error:nil];
        } else {
            [self.xmppStream authenticateWithPassword:self.myPassword error:nil];
        }
    }
    
    - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
    {
        NSLog(@"%s",__func__);
    }
    
    //登录失败
    - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
    {
        NSLog(@"%s",__func__);
    }
    
    //登录成功
    - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
    {
        NSLog(@"%s",__func__);
        
        [self goOnline];
        
        [[NSNotificationCenter defaultCenter] postNotificationName:kLOGIN_SUCCESS object:nil];
    }
    
    
    @end

    然后是登录功能:

    登录按钮的action如下:

    #pragma mark - click event
    /** 登录事件 */
    - (IBAction)loginClick:(id)sender {
        NSString *username = _usernameField.text;
        NSString *password = _passwordField.text;
        
        NSString *message = nil;
        if (username.length <= 0) {
            message = @"用户名未填写";
        } else if (password.length <= 0) {
            message = @"密码未填写";
        }
        
        if (message.length > 0) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil];
            [alertView show];
        } else {
            [[JKXMPPTool sharedInstance] loginWithJID:[XMPPJID jidWithUser:username domain:@"im.joker.cn" resource:@"iOS"] andPassword:password];
        }
    }
    用通知返回登录成功的消息

    - (void)loginSuccess
    {
        NSLog(@"loginSuccess");
        
        [self performSegueWithIdentifier:@"loginSegue" sender:self];
    }

    再然后实现注册的功能:


    - (IBAction)registAction:(id)sender {
        NSString *username = _usernameField.text;
        NSString *password = _passwordField.text;
        NSString *confirm = _confirmField.text;
        
        NSString *message = nil;
        if (username.length <= 0) {
            message = @"用户名未填写";
        } else if (password.length <= 0) {
            message = @"密码未填写";
        } else if (confirm.length <= 0) {
            message = @"确认密码未填写";
        }
        
        if (message.length > 0) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil];
            [alertView show];
        } else if (![password isEqualToString:confirm]) {
            message = @"密码与确认密码不一致";
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil];
            [alertView show];
        } else {
            [[JKXMPPTool sharedInstance] registerWithJID:[XMPPJID jidWithUser:username domain:@"im.joker.cn" resource:@"iOS"] andPassword:password];
        }
    }
    因为注册时,不需要进行认证,注册会直接返回BOOL结果,所以改进连接代理方法:

    //这个是xml流初始化成功
    - (void)xmppStreamDidConnect:(XMPPStream *)sender
    {
        NSLog(@"%s",__func__);
        if (self.xmppNeedRegister) {
            BOOL result = [self.xmppStream registerWithPassword:self.myPassword error:nil];
            NSNumber *number = [NSNumber numberWithBool:result];
            
            [[NSNotificationCenter defaultCenter] postNotificationName:kREGIST_RESULT object:number];
            
        } else {
            [self.xmppStream authenticateWithPassword:self.myPassword error:nil];
        }
    }

    下载地址:点击下载

    github地址:https://github.com/Joker-King/ChatDemo




  • 相关阅读:
    方法的重载理解
    JAVA 三种循环的总结
    模拟时间倒计时
    制作漂浮广告效果
    js+css+html实现抽奖小程序
    将系统时间转换为汉字表示的四种方法
    简单的导航栏
    模仿光标闪烁,光标移动,自动切换背景
    sublime插件emmet安装和使用
    现在有一张半径为r的圆桌,其中心位于(x,y),现在他想把圆桌的中心移到(x1,y1)。每次移动一步,都必须在圆桌边缘固定一个点然后将圆桌绕这个点旋转。问最少需要移动几步。
  • 原文地址:https://www.cnblogs.com/wanghang/p/6298867.html
Copyright © 2011-2022 走看看