(十)即時通訊之XMPPFramework登陸注冊

前言

這也是本人第一次琢磨關于即時通訊方面的內容,結合網上查看的相關資料搭建出來的仿微信小demo,如有意見請多多指教

寫了這么多,尼瑪終于到正題了,前面9篇講的都是基本概念及相關環(huán)境的搭建,這里列舉一下:

  • Sokcet套接字的簡介
  • 網絡七層協(xié)議,TCP/UDP的概念
  • CocoaSocket的使用
  • XMPP協(xié)議的簡介
  • XMPP通訊環(huán)境SQL的搭建
  • XMPP通訊環(huán)境服務器openfire的搭建
  • XMPP通訊環(huán)境客戶端message,Aduim,Spark的搭建
  • XMPPFramework框架的導入及簡單介紹

具體項目可以在githubWeiChat下載進行查看,如若各位看官老爺覺得還可以請點star

下面開始進入正題
XMPPFramework的使用

看圖

  • 用戶注冊


    注冊.gif
  • 登陸


    登陸
  • 切換用戶登陸


    切換用戶登陸.gif
  • 注銷


    注銷

今天講的是XMPP的登陸注冊部分,廢話不多說:

1.登陸注冊部分常用的對象

  • XMPPStream XMPP通道:負責XMPP信息的傳輸以及傳輸狀態(tài)等
  • XMPPReconnect 自動連接

2.準備工作

1.創(chuàng)建一個單例類名為XMPPManager,負責XMPP相關管理工作,比如各類登陸注冊模塊的激活,實現(xiàn)都在這里進行處理.
2.創(chuàng)建一個單例類名為UserManager,負責用戶的賬號密碼的管理以及獲取用戶信息等方面.

3.登錄注冊實現(xiàn)部分

3.1實現(xiàn)原理

這里闡述下實現(xiàn)原理,具體實現(xiàn)過程請參考下部分代碼以及項目內容.

 1.導入XMPPStream,XMPPReonnect頭文件
 2.激活XMPPStream,XMPPReconnect模塊并設置代理
 3.登錄的流程:
  xmpp的登錄流程是权旷,
  3.1 傳遞 JID , Host , Port 先連接上服務器 
  3.2連接成功了 再 發(fā)送密碼到服務器 倒源,
  3.3授權成功 或者 授權失敗.這就代表登陸成功或失敗,成功了則跳到微信主界面

 4.注冊的流程:
   4.1xmpp的注冊流程是, 傳遞 JID , Host , Port 先連接上服務器 :
通過JID連接成功
連接成功則會自動調用XMPPStreamDelegatexmppStreamDidConnect 代理方法
然后在通過代理方法調用 XMPPStream的發(fā)送密碼的方法authenticateWithPassword
   4.2連接成功了 再 發(fā)送注冊密碼到服務器 
   4.3注冊成功 或者 失敗,注冊成功了跳到登陸界面,進行登陸

共同點:
不管你jid存不存在 都能連接到服務器嗡善。

不同點:
發(fā)送的是授權密碼 還是 發(fā)送注冊密碼 就是決定你是登錄還是注冊.
5.在登陸注冊頁面進行調用方法并傳遞狀態(tài)

注意:
1.連接到服務器后,對于是登陸還是注冊的判斷
2.登陸成功后需要發(fā)送一個在線狀態(tài)消息,離線了需要發(fā)送離線狀態(tài)消息
3.在UserManager中登陸用戶信息和注冊用戶信息分清楚
4.XMPPStream代理方法執(zhí)行的順序先后
5.block對于登陸注冊狀態(tài)的提示
6.對于XMPP JID的理解,用戶名@服務器地址.設備信息(可選)

詳細請看demo
7.這個demo里登錄名就是密碼,不影響使用,請注意

3.2XMPPManager部分

3.2.1單例類
#pragma mark 創(chuàng)建XMPPManager單例類
singleton_m(manager)
3.2.2創(chuàng)建XMPPStream對象
// 登錄注冊什么的都是和服務器交互,所以我們用到的類就是XMPPStream
- (void)connect {
    if (!self.stream) {
        // 創(chuàng)建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的發(fā)送密碼的方法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   : yoyu@127.0.0.1.iPhone
    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   : yoyu@127.0.0.1.iPhone
    self.stream.myJID = [XMPPJID jidWithUser:user.registName domain:kHostName resource:@"iPhone"];
    
    // 通過讀取UserDefault中的name連接服務器
    [self connectToServer];
}
3.2.5用戶注銷
- (void)xmppUserLogout {
    // 發(fā)送離線狀態(tài)
    [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連接服務器狀態(tài)
#pragma mark -- XMPPStreamDelegate
/**
 *  登錄的流程:
    xmpp的登錄流程是渡蜻, 傳遞 JID , Host , Port 先連接上服務器 术吝,連接成功了 再 發(fā)送密碼到服務器 ,授權成功 或者 授權失敗
 
    注冊的流程:
    xmpp的注冊流程是茸苇, 傳遞 JID , Host , Port 先連接上服務器 排苍,連接成功了 再 發(fā)送注冊密碼到服務器 ,注冊成功 或者 失敗
 
    共同點:
    不管你jid存不存在 都能連接到服務器学密。
 
    不同點:
    發(fā)送的是授權密碼 還是 發(fā)送注冊密碼 就是決定你是登錄還是注冊

 */
/**
    通過JID連接成功
 *  連接成功則會自動調用XMPPStreamDelegatexmppStreamDidConnect 代理方法
    然后在通過代理方法調用 XMPPStream的發(fā)送密碼的方法authenticateWithPassword
 */
#pragma mark -- 連接成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
    NSLog(@"通過JID建立連接成功");
    /**
     *  發(fā)送密碼進行授權登陸
        分登陸密碼
        和注冊密碼
        需要判斷
     */
    UserManager *user = [UserManager sharedmanager];
    //[user readUserInfo];
    NSError *error = nil;
    NSLog(@"%@",user.loginName);
    NSLog(@"---%@",user.registName);
    if (user.loginName) {
        // 發(fā)送登陸密碼
        [self.stream authenticateWithPassword:user.loginPsw error:&error];
    } else {
        // 發(fā)送注冊密碼
        [self.stream registerWithPassword:user.registPsw error:&error];
    }
}

#pragma mark -- 連接失敗,與服務器斷開連接(例如網絡原因)
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error {
    NSLog(@"通過JID建立連接失敗,與服務器斷開連接");
    if (self.block) {
        self.block(XMPPUserStateTypeOther);
    }
    
    // 發(fā)送通知:狀態(tài)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];
    
    // 同時要發(fā)送一個在線的信息
    [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登陸狀態(tài)發(fā)送
#pragma mark ******************************
#pragma mark - 登陸成功后,給服務器發(fā)送一個在線消息:上線了
/**
    presence表示用戶狀態(tài)
 
   presence 的狀態(tài):
        available 上線
        away 離開
        do not disturb 忙碌
        unavailable 下線
 */
- (void)sendOnlineMessage {
    /**
     *  關于用戶的上線和下線淘衙,需要用到一個類XMPPPresence 類。這個類是XMPPElement的子類腻暮,主要用來管理某些信息的展現(xiàn)彤守。首先要實例化一個對象,這其中會用到一個presenceWithType 方法哭靖,有兩個選擇@"unavailable"代表下線具垫,@"available"代表上線,一般情況上線的時候后面就可以直接省略试幽。
     */
    XMPPPresence *pre = [XMPPPresence presenceWithType:@"available"];
    // XMPPPresence *pre = [XMPPPresence presence];
    [self.stream sendElement:pre];
}

#pragma mark - 離線時,給服務器發(fā)送一個在線消息:下線了
- (void)sendOfflineMessage {
    XMPPPresence *pre = [XMPPPresence presenceWithType:@"unavailable"];
    [self.stream sendElement:pre];
}

3.3登陸注冊頁面
這個部分就不詳細介紹了,可以進demo查閱

未完待續(xù)...

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末筝蚕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子铺坞,更是在濱河造成了極大的恐慌起宽,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件济榨,死亡現(xiàn)場離奇詭異坯沪,居然都是意外死亡,警方通過查閱死者的電腦和手機擒滑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門腐晾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人橘忱,你說我怎么就攤上這事赴魁⌒斗睿” “怎么了钝诚?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長榄棵。 經常有香客問我凝颇,道長潘拱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任拧略,我火速辦了婚禮芦岂,結果婚禮上,老公的妹妹穿的比我還像新娘垫蛆。我一直安慰自己禽最,他們只是感情好,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布袱饭。 她就那樣靜靜地躺著川无,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虑乖。 梳的紋絲不亂的頭發(fā)上懦趋,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音疹味,去河邊找鬼仅叫。 笑死,一個胖子當著我的面吹牛糙捺,可吹牛的內容都是我干的诫咱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼继找,長吁一口氣:“原來是場噩夢啊……” “哼遂跟!你這毒婦竟也來了?” 一聲冷哼從身側響起婴渡,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤幻锁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后边臼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哄尔,經...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年柠并,在試婚紗的時候發(fā)現(xiàn)自己被綠了岭接。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡臼予,死狀恐怖鸣戴,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情粘拾,我是刑警寧澤窄锅,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站缰雇,受9級特大地震影響入偷,放射性物質發(fā)生泄漏追驴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一疏之、第九天 我趴在偏房一處隱蔽的房頂上張望殿雪。 院中可真熱鬧,春花似錦锋爪、人聲如沸丙曙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽河泳。三九已至,卻和暖如春年栓,著一層夾襖步出監(jiān)牢的瞬間拆挥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工某抓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纸兔,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓否副,卻偏偏與公主長得像汉矿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子备禀,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容