XMPP系列(二)----用戶註冊和用戶登陸功能

1.建立一個新工程html



2.導入XMPP框架git

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

將XMPP的幾個文件夾拖進工程中,須要的文件以下:服務器


而後把Sample_XMPPFramework.h更名爲XMPPFramework.h框架

接下來導入兩個依賴庫:libresolv.dylib和libxml2.dylib,而後添加header search:dom


再添加一個pch文件socket


在pch文件中添加以下代碼:工具

#ifdef __OBJC__
    #import <UIKit/UIKit.h>

    #import "XMPPFramework.h"
#endif
再而後設置工程的pch文件



$SRCROOT後面是項目名/pch文件名。post

作完以上步驟,項目就能夠編譯成功啦!atom

如今開始搭建項目的登陸界面:

首先封裝一個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

相關文章
相關標籤/搜索