程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> XMPPFramework

XMPPFramework

編輯:C++入門知識

XMPPFramework

GitHub: https://github.com/robbiehanson/XMPPFramework

獲取源代碼

git clone https://github.com/robbiehanson/XMPPFramework.git

checkout XMPPFramework 一個最新的 branch

添加依賴

> 拷貝 /Vendor/CocoaLumberjack 到項目根目錄下,add files...,選擇 CocoaLumberjack 文件夾

> 同樣的步驟,拷貝 CocoaAsyncSocket 和 KissXML 並添加到項目中

CocoaAsyncSocket 依賴 CFNetwork.framework 和 Security.framework,在 TARGETS -> Build Phases -> Link Binary With Libraries 添加

KissXML 使用了 libxml2 解析 XML,所以

首先,我們需要在 TARGETS -> Build Phases -> Link Binary With Libraries 添加 libXML2.dylib

然後,在 TARGETS -> Build Settings -> Other Linker Flags 添加 -lxml2,TARGETS -> Build Settings -> Header Search Paths 添加 /usr/include/libxml2

> 拷貝 /Vendor/libidn 到項目根目錄下,添加靜態庫文件 libidn.a 和頭文件 idn-int.h 和 stringprep.h

添加 XMPPFramework

拷貝源碼目錄下的 Authentication Categories Core 和 Utilities 到項目根目錄下並添加到項目中

此外,需要添加動態連接庫 libresolv.dylib ,在 TARGETS -> Build Phases -> Link Binary With Libraries 添加

添加擴展

你可以根據自己的需要,添加 /Extensions 的擴展到項目中

你可能遇到的問題:

> "XMPPFramework.h" file not found

XMPPFramework.h 內容如下,可根據實際使用模塊進行刪改:

復制代碼
#import "XMPP.h"

// List the modules you're using here.

#import "XMPPReconnect.h"

#import "XMPPRoster.h"
#import "XMPPRosterCoreDataStorage.h"

#import "XMPPvCardTempModule.h"
#import "XMPPvCardAvatarModule.h"
#import "XMPPvCardCoreDataStorage.h"

#import "XMPPCapabilities.h"
#import "XMPPCapabilitiesCoreDataStorage.h"

#import "XMPPMUC.h"
#import "XMPPRoomCoreDataStorage.h"
復制代碼

還有一些問題,是由於沒有添加Extension需要的依賴庫所產生的

可在 TARGETS -> Build Phases -> Link Binary With Libraries 添加

CoreData.framework SystemConfiguration.framework CoreLocation.framework

ARC 警告

XMPPFramework 使用 ARC,如果你的項目沒有使用 ARC,build 之後你會得到許許多多的 ARC 警告。

不要忽視這些警告,它會導致你的程序因 memory leak 而崩潰……

Edit -> Refactor -> convert to Objective-C ARC,消滅這些警告!

參考: https://github.com/robbiehanson/XMPPFramework/wiki/GettingStarted_iOS



用戶登錄

准備工作

比較知名的開源XMPP服務器:一個是Openfire,一個是ejabberd

Openfire 使用 Java 語言編寫,比較容易上手,地址:http://www.igniterealtime.org/projects/openfire/

ejabberd 使用 Erlang 語言編寫,是一款非常知名的 Erlang 開源項目,地址:http://www.ejabberd.im/

安裝 ejabberd,可以參考我的博客:【ejabberd】安裝XMPP服務器ejabberd(Ubuntu 12.04)

搭建一個自己的 XMPP 服務器之後,就讓我們開始吧!

連接服務器

1、新建一個 XMPPStream 對象,添加委托

添加委托方法 - (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue

參數 delegateQueue 為委托回調所使用的 GCD 隊列,dispatch_get_main_queue() 獲取主線程 GCD 隊列

2、設置 JID 和 主機名

JID 一般由三部分構成:用戶名,域名和資源名,例如 [email protected]/Anthony

如果沒有設置主機名,則使用 JID 的域名作為主機名

端口號是可選的,默認是 5222

3、連接

復制代碼
- (void)connect {
    if (self.xmppStream == nil) {
        self.xmppStream = [[XMPPStream alloc] init];
        [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
    }
    
    if (![self.xmppStream isConnected]) {
        NSString *username = [[NSUserDefaults standardUserDefaults] objectForKey:@"username"];
        XMPPJID *jid = [XMPPJID jidWithUser:username domain:@"lizhen" resource:@"Ework"];
        [self.xmppStream setMyJID:jid];
        [self.xmppStream setHostName:@"10.4.125.113"];
        NSError *error = nil;
        if (![self.xmppStream connect:&error]) {
            NSLog(@"Connect Error: %@", [[error userInfo] description]);
        }
    }
}
復制代碼

身份認證

實現 - (void)xmppStreamDidConnect:(XMPPStream *)sender 委托方法

連接服務器成功後,回調該方法

This method is called after the XML stream has been fully opened. More precisely, this method is called after an opening and tag have been sent and received, and after the stream features have been received, and any required features have been fullfilled. At this point it's safe to begin communication with the server.

身份認證方法 - (BOOL)authenticateWithPassword:(NSString *)inPassword error:(NSError **)errPtr

復制代碼
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
    NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:@"password"];
    NSError *error = nil;
    if (![self.xmppStream authenticateWithPassword:password error:&error]) {
        NSLog(@"Authenticate Error: %@", [[error userInfo] description]);
    }
}
復制代碼

上線

實現 - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender 委托方法

身份認證成功後,回調該方法

This method is called after authentication has successfully finished.

If authentication fails for some reason, the xmppStream:didNotAuthenticate: method will be called instead.

新建一個 XMPPPresence 對象,類型為 available,發送!

- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];
    [self.xmppStream sendElement:presence];
}

退出並斷開連接

新建一個 XMPPPresence 對象,類型為 unavailable,發送!

斷開連接

復制代碼
- (void)disconnect {
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
    [self.xmppStream sendElement:presence];
    
    [self.xmppStream disconnect];
}

好友狀態

獲取好友狀態,通過實現

- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence

方法

當接收到

 標簽的內容時,XMPPFramework 框架回調該方法

一個

 標簽的格式一般如下:

  這裡是顯示的內容

  這裡是顯示的狀態

presence 的狀態:

available 上線

away 離開

do not disturb 忙碌

unavailable 下線

復制代碼
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
    NSString *presenceType = [presence type];
    NSString *presenceFromUser = [[presence from] user];
    if (![presenceFromUser isEqualToString:[[sender myJID] user]]) {
        if ([presenceType isEqualToString:@"available"]) {
            //
        } else if ([presenceType isEqualToString:@"unavailable"]) {
            //
        }
    }
}


接收消息

通過實現

- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message;

方法

當接收到 標簽的內容時,XMPPFramework 框架回調該方法

根據 XMPP 協議,消息體的內容存儲在標簽 內

- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
    NSString *messageBody = [[message elementForName:@"body"] stringValue];
}

發送消息

發送消息,我們需要根據 XMPP 協議,將數據放到 標簽內,例如:

  Hello World!

復制代碼
- (void)sendMessage:(NSString *) message toUser:(NSString *) user {
    NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
    [body setStringValue:message];
    NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
    [message addAttributeWithName:@"type" stringValue:@"chat"];
    NSString *to = [NSString stringWithFormat:@"%@@example.com", user];
    [message addAttributeWithName:@"to" stringValue:to];
    [message addChild:body];
    [self.xmppStream sendElement:message];
}



好友列表

好友列表,在 XMPP 中被稱為 roster,花名冊?

獲取 roster 需要客戶端發送 標簽向 XMPP 服務器端查詢

一個 IQ 請求:

  from="[email protected]"

  to="example.com"

  id="1234567">

  

type 屬性,說明了該 iq 的類型為 get,與 HTTP 類似,向服務器端請求信息

from 屬性,消息來源,這裡是你的 JID

to 屬性,消息目標,這裡是服務器域名

id 屬性,標記該請求 ID,當服務器處理完畢請求 get 類型的 iq 後,響應的 result 類型 iq 的 ID 與 請求 iq 的 ID 相同

子標簽,說明了客戶端需要查詢 roster

復制代碼
- (void)queryRoster {
    NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:roster"];
    NSXMLElement *iq = [NSXMLElement elementWithName:@"iq"];
    XMPPJID *myJID = self.xmppStream.myJID;
    [iq addAttributeWithName:@"from" stringValue:myJID.description];
    [iq addAttributeWithName:@"to" stringValue:myJID.domain];
    [iq addAttributeWithName:@"id" stringValue:[self generateID]];
    [iq addAttributeWithName:@"type" stringValue:@"get"];
    [iq addChild:query];
    [self.xmppStream sendElement:iq];
}
復制代碼

一個 IQ 響應:

  id="1234567"

  to="[email protected]">

  

    

    

  

type 屬性,說明了該 iq 的類型為 result,查詢的結果

標簽的子標簽 ,為查詢的子項,即為 roster

item 標簽的屬性,包含好友的 JID,和其它可選的屬性,例如昵稱等。

通過實現

- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq;

方法

當接收到 標簽的內容時,XMPPFramework 框架回調該方法

復制代碼
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {
    if ([@"result" isEqualToString:iq.type]) {
        NSXMLElement *query = iq.childElement;
        if ([@"query" isEqualToString:query.name]) {
            NSArray *items = [query children];
            for (NSXMLElement *item in items) {
                NSString *jid = [item attributeStringValueForName:@"jid"];
                XMPPJID *xmppJID = [XMPPJID jidWithString:jid];
                [self.roster addObject:xmppJID];
            }
        }
    }
}




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved