美文网首页
XMPP(更新中...)

XMPP(更新中...)

作者: 简简简简简书 | 来源:发表于2016-06-02 22:30 被阅读113次

    XMPP(更新中...)

    什么是XMPP

    • XMPP协议是由JSF开源组织开发的,不属于任何机构,保证了开放性
    • XMPP是一种典型的C/S架构,基本的网络形式是通过TCP/IP连接到服务器,通过socket建立连接,传输的是XML数据
    • XMPP是基于XML建立的,具有良好的扩展性
    • XMPP与HTTP:XMPP与HTTP都是协议,HTTP协议是短连接,常用于网络上不定时的数据请求,XMPP是一种长连接,基于XML的即时通讯的协议
    • XMPP本身是协议,JSF在socket原理的基础上,加入XMPP协议,定义出了叫XMPP的framework,它实现了即时通讯基本的功能:注册,登录,好友,收发消息等等;
    • XMPP只实现了消息的收发,并没有定义附件(视频,音频,文件)的收发,所以需要我们自己手动封装收发附件的方法

    搭建即时通讯环境

    • XMPP只提供了一套框架,所以服务器端需要我们自己集成
    • 网上有很多详细介绍即时通讯服务器的文章,这里不做过多的说明
    • 大概的顺序:xampp下载 - openfire下载(java环境,如果没有就先集成) -
      xampp(建立数据库) - oeprfire搭建服务器, 到这里可以选择用spark做测试,也可以自己写客户端做测试

    XMPP的基本用法

    注册和登录

    • 无论注册还是登陆,都需要初始化一个消息通道类(XMPPStream),一把情况下会抽出一个单利,来封装这些功能,所以把初始化写在单利的初始化中
    /**  保存登录用户名 */
    @property (nonatomic,copy) NSString *loginUserName;
    /**  登录or注册 */(这里记录是登陆还是注册,为了在连接成功的时候,判断是验证密码还是向服务器发送密码)
    @property (nonatomic,assign) ConnectType connectType;
    
    
    
    /** 初始化 */
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            //初始化消息通道
            self.stream = [[XMPPStream alloc] init];
            //设置域名
            self.stream.hostName = kHostName;
            //设置端口
            self.stream.hostPort = kHostPort;
            //添加代理
            [self.stream addDelegate:self delegateQueue:dispatch_get_main_queue()];
        }
        return self;
    }
    #pragma mark  连接的代理方法
    //连接超时
    - (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
    {
        if (self.loginFail) {
            DDXMLElement *error = [DDXMLElement elementWithName:@"连接超时"];
            self.loginFail(error);
        }
    }
    //连接成功
    - (void)xmppStreamDidConnect:(XMPPStream *)sender
    {
        switch (self.connectType) {
                //登录状态
            case ConnectTypeLogin:
                //验证密码
                [self.stream authenticateWithPassword:self.loginPassword error:nil];
                break;
                //注册状态
            case ConnectTypeRegist:
                //发送密码
                [self.stream registerWithPassword:self.registPassword error:nil];
                break;
        }
    }
    //连接断开
    - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
    {
        if (error) {
            NSError *err = nil;
            [self.stream connectWithTimeout:-1 error:&err];
        }
    }
    
    • 注册
    /**  保存注册密码 */
    @property (nonatomic,copy) NSString *registPassword;
    /**  注册成功block */
    @property (nonatomic,copy) void (^registSuccess)(id);
    /**  注册失败的block */
    @property (nonatomic,copy) void (^registFail)(DDXMLElement *);
    
    
    
    /** 注册 */
    - (void)registWithUserName:(NSString *)userName password:(NSString *)password success:(void(^)(id data))success fail:(void(^)(DDXMLElement *error))fail
    {
        //标记状态为注册
        self.connectType = ConnectTypeRegist;
        //连接服务器
        self.stream.myJID = [XMPPJID jidWithUser:userName domain:kDomin resource:kResource];
        //判断是否在连接状态(这里防止循环注册问题,即已经连接成功了,就应该断开再去注册)
        if ([self.stream isConnected] || [self.stream isConnecting]) {
            //断开连接
            [self.stream disconnect];
        }
        [self.stream connectWithTimeout:-1 error:nil];
        //保存传入的值(由于要在代理方法中才能发送密码,接收到是否注册成功,所以定义属性保存各个值)
        self.registPassword = password;
        self.registSuccess = success;
        self.registFail = fail;
    }
    #pragma mark 注册的代理方法
    //注册成功
    - (void)xmppStreamDidRegister:(XMPPStream *)sender
    {
        if (self.registSuccess) {
            self.registSuccess(@"注册成功");
        }
    }
    //注册失败
    - (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error
    {
        if (self.registFail) {
            self.registFail(error);
        }
    }
    
    • 登录(原理跟注册相似)
    /**  保存登录密码 */
    @property (nonatomic,copy) NSString *loginPassword;
    /**  登录成功block */
    @property (nonatomic,copy) void (^loginSuccess)(id);
    /**  登录失败的block */
    @property (nonatomic,copy) void (^loginFail)(DDXMLElement *);
    
    
    
    /** 登录 */
    - (void)loginWithUserName:(NSString *)userName password:(NSString *)password success:(void(^)(id data))success fail:(void(^)(DDXMLElement *error))fail
    {
        //标记状态是登录
        self.connectType = ConnectTypeLogin;
        //设置1.用户名 2.域名 3.信息来源(ios或者Android)
        self.stream.myJID = [XMPPJID jidWithUser:userName domain:kDomin resource:kResource];
        //判断是否在连接状态
        if ([self.stream isConnected] || [self.stream isConnecting]) {
            //断开连接
            [self.stream disconnect];
        }
        //连接服务器
        [self.stream connectWithTimeout:-1 error:nil];
        //保存传入的值
        self.loginUserName = userName;
        self.loginPassword = password;
        self.loginSuccess = success;
        self.loginFail = fail;
    }
    #pragma mark 登录的代理方法
    //认证成功
    - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
    {
        //存入本地(是否是登录状态,用户名,密码)(如果登陆成功,这里做了个自动登录,自动登录实际就是查看本地是否有登录记录,有就在appdelegate中直接调用登录的方法)
        KDefaultSetValue(KIsLogin, @"login");
        KDefaultSetValue(@"userName", self.loginUserName);
        KDefaultSetValue(@"password", self.loginPassword);
        if (self.loginSuccess) {
            self.loginSuccess(@"登录成功");
        }
    }
    //认证失败
    - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
    {
        if (self.loginFail) {
            self.loginFail(error);
        }
    }
    
    • 注销:
      • 要断开与服务器的连接
      • 要把本地存储的登录信息移除
    /** 注销 */
    - (void)logout
    {
        //断开连接
        [self.stream disconnect];
        //清除本地缓存
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"userName"];
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"password"];
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:KIsLogin];
    }
    

    相关文章

      网友评论

          本文标题: XMPP(更新中...)

          本文链接:https://www.haomeiwen.com/subject/sqmkdttx.html