Xmpp學(xué)習(xí)之Android-smack入門(mén)指導(dǎo)

版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載楣富。

轉(zhuǎn)載請(qǐng)表明出處:http://www.reibang.com/p/049ef7d049eb

[TOC]
WTF簡(jiǎn)書(shū)不支持 toc 目錄模式,簡(jiǎn)單截圖一張汛骂。


img-w140
img-w140

在此為后面的smack學(xué)習(xí)做筆記竟终,以作備忘茎毁。
以下是本次采用的Demo環(huán)境:

  • Openfire 4.3.8.2
  • smack4.2.1

smack之登錄

xmpp首次登錄卧檐,可以通過(guò)自定義的Socket去進(jìn)行連接服務(wù)器墓懂,如果你服務(wù)器不是配置了非常特殊TLS連接,一般可以是用Smack中的XMPPConnection類(lèi)建立連接(我推薦通過(guò)API中的XMPPConnection去連接霉囚,能省去很多復(fù)雜的過(guò)程)捕仔,下面我講一下XMPPConnection的連接配置。

基礎(chǔ)配置

XMPPConnection的連接需要通過(guò)XMPPTCPConnectionConfiguration.builder()配置你在Openfire設(shè)置的配置盈罐,代碼如下:

XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder();
builder.setXmppDomain("server domain");
builder.setHostAddress(InetAddress.getByName("you host address"));
//default port 5222
builder.setPort(you port);
builder.setDebuggerEnabled(true);
builder.setCompressionEnabled(true);
builder.setSendPresence(false);
builder.setUsernameAndPassword("username", "password");

像如上代碼中的榜跌,XmppDomain是必須配置(這里的```XmppDomain```會(huì)拼接在首次建立```Socket```的IQ中的to和from中),HostAddress是你運(yùn)行服務(wù)器的域名或IP地址盅粪,Port是你登錄的端口钓葫,在Openfire中默認(rèn)是5222端口,但如果你的服務(wù)器使用的是Nginx做前置機(jī)票顾,那么這里你需要填入你的Nginx配置的端口础浮。  

### 進(jìn)階配置
可能看到這里,你會(huì)覺(jué)得很奇怪库物,為什么還有個(gè)進(jìn)階配置霸旗,難道Openfire難道登錄就是一個(gè)普通的Socket登錄嗎?這樣很容易被黑吧戚揭,沒(méi)錯(cuò),實(shí)際上還有進(jìn)階配置滿(mǎn)足加密連接和自定義的要求撵枢,如TLS登錄或SSL登錄或者壓縮通訊民晒,如下例子: 

* 如自定義的TLS登錄  
TLS的登錄方式精居,具體筆者也沒(méi)實(shí)踐過(guò),歡迎拍磚潜必。

```Java
SSLContext sslContext = SSLContext.getInstance("TLS");

MemorizingTrustManager mtm = new MemorizingTrustManager(getApplicationContext());

MemorizingKeyManager memorizingKeyManager = new MemorizingKeyManager(getApplicationContext(), "123456");

sslContext.init(new X509KeyManager[]{(X509KeyManager) memorizingKeyManager}
   , new X509TrustManager[]{mtm}, new java.security.SecureRandom());
   
builder.setCustomSSLContext(sslContext);

builder.setHostnameVerifier(mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier())); 

以上的代碼需要注意一點(diǎn)是內(nèi)中的MemorizingTrustManager,他來(lái)自于MemorizingTrustManager,而另外一個(gè)MemorizingKeyManager是自定義的類(lèi)靴姿,內(nèi)中的代碼其實(shí)就是自定義了一個(gè)繼承自X509TrustManager的類(lèi),這里不做深究磁滚,如有需要可以聯(lián)系我佛吓。

  • 使用舊的TLS連接
    實(shí)際上這里的意思是關(guān)閉安全模式,可以通過(guò)如下代碼關(guān)閉安全模式
* 其他的兼容方式  
    實(shí)際上就是沿用上面的那個(gè)函數(shù)```builder.setSecurityMode```中填入的另外兩種方式垂攘,以下是這三種方式的注釋和描述:
    
```JavaDoc
/**
 * Security via TLS encryption is required in order to connect. If the server
 * does not offer TLS or if the TLS negotiation fails, the connection to the server
 * will fail.
 */
required,

/**
 * Security via TLS encryption is used whenever it's available. This is the
 * default setting.
 * <p>
 * <b>Do not use this setting</b> unless you can't use {@link #required}. An attacker could easily perform a
 * Man-in-the-middle attack and prevent TLS from being used, leaving you with an unencrypted (and
 * unauthenticated) connection.
 * </p>
 */
ifpossible,

/**
 * Security via TLS encryption is disabled and only un-encrypted connections will
 * be used. If only TLS encryption is available from the server, the connection
 * will fail.
 */
disabled
  • 開(kāi)啟通訊壓縮
    這里的通訊壓縮開(kāi)啟后维雇,傳輸?shù)牧髁繉⒐?jié)省90%
builder.setCompressionEnabled(true);
  • SASL認(rèn)證
    Openfire服務(wù)器默認(rèn)支持 PLAIN 、ANONYMOUS 晒他、JIVE-SHAREDSECRET吱型,這里我的服務(wù)器開(kāi)啟的是 PLAIN ,所以我使用 PLAIN
SASLAuthentication.blacklistSASLMechanism(SASLPlainMechanism.NAME);

登錄服務(wù)器

通過(guò)了上面的配置后陨仅,咱們可以登錄Openfire系統(tǒng)了立轧,相當(dāng)簡(jiǎn)單:

AbstractXMPPConnection xmpptcpConnection = new XMPPTCPConnection(builder.build());
if (!xmpptcpConnection.isConnected()) {
    xmpptcpConnection.connect();
}else{
    System.out.println("Already connected");
}

如果以上的配置和服務(wù)器的自定義不匹配牌柄,在建立連接的這一步會(huì)拋出異常,具體的異常可以通過(guò)對(duì)應(yīng)方案處理澈段,這里不詳談。

登錄底層報(bào)文通訊簡(jiǎn)要解析

作為程序猿栈顷,難道會(huì)使用API夠了嗎秋麸?不,我們繼續(xù)折騰猾警,下面一起來(lái)看一下底層的通訊報(bào)文流程孔祸。

  • 在建立了Socket后,client會(huì)向服務(wù)器發(fā)出一條xml
SENT
<stream:stream 
    xmlns='jabber:client'   
    to='server domain' 
    xmlns:stream='http://etherx.jabber.org/streams' 
    version='1.0' 
    from='username@server domain' 
    xml:lang='en'>
  • 服務(wù)器解析到上面的指令后发皿,會(huì)返回用于告訴client可選的SASL方式
RECV
<?xml version='1.0' encoding='UTF-8'?>
    <stream:stream xmlns:stream="http://etherx.jabber.org/streams"  
    xmlns="jabber:client" 
    from="im" 
    id="c997c3a8" 
    xml:lang="en" 
    version="1.0">
        <stream:features>
        <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls">
        </starttls>
        <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
            <mechanism>PLAIN</mechanism>
            <mechanism>ANONYMOUS</mechanism>
            <mechanism>JIVE-SHAREDSECRET</mechanism>
        </mechanisms>
        <compression xmlns="http://jabber.org/features/compress">
            <method>zlib</method>
        </compression>
        <auth xmlns="http://jabber.org/features/iq-auth"/>
        <register xmlns="http://jabber.org/features/iq-register"/>
    </stream:features>
  • 客戶(hù)端選擇ANONYMOUS認(rèn)證方式
SENT
<auth 
    xmlns='urn:ietf:params:xml:ns:xmpp-sasl'    
    mechanism='ANONYMOUS'>=</auth>
  • 服務(wù)器通過(guò)計(jì)算加密后的密碼后崔慧,服務(wù)器將返回
RECV
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
  • 當(dāng)客戶(hù)端收到以上命令后,將首次發(fā)起連接的id發(fā)送到服務(wù)器
SENT
<stream:stream 
    xmlns='jabber:client' 
    to='server domain' 
    xmlns:stream='http://etherx.jabber.org/streams' 
    version='1.0'
    from='username@server domain' 
    id='c997c3a8' 
    xml:lang='en'>
  • 這時(shí)服務(wù)器會(huì)返回如下內(nèi)容說(shuō)明此時(shí)的已經(jīng)成功綁定了當(dāng)前的Socket穴墅,
RECV
<?xml version='1.0' encoding='UTF-8'?>
    <stream:stream 
        xmlns:stream="http://etherx.jabber.org/streams" 
        xmlns="jabber:client" 
        from="im" 
        id="c997c3a8" 
        xml:lang="en"
        version="1.0">
            <stream:features>
                <compression 
                    xmlns="http://jabber.org/features/compress">
                    <method>zlib</method>
                </compression>
                <bind 
                    xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
                    <session 
                        xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
    </stream:features>
  • 客戶(hù)端在接收到如上的內(nèi)容后會(huì)告訴服務(wù)器開(kāi)啟壓縮
SENT
<compress xmlns='http://jabber.org/protocol/compress'><method>zlib</method></compress>
  • 服務(wù)器返回
RECV
<compressed xmlns='http://jabber.org/protocol/compress'/>
  • 客戶(hù)端收到服務(wù)器的響應(yīng)命令后惶室,重新建立一個(gè)Socket,發(fā)送指令
SENT
<stream:stream 
    xmlns='jabber:client'       
    to='server domain' 
    xmlns:stream='http://etherx.jabber.org/streams' 
    version='1.0' 
    from='username@server domain'  
    id='c997c3a8' 
    xml:lang='en'>
  • 服務(wù)器將返回玄货,不知道你有沒(méi)有發(fā)現(xiàn)皇钞,這里的id="c997c3a8"還是那個(gè)id
RECV
<?xml version='1.0' encoding='UTF-8'?>
    <stream:stream 
        xmlns:stream="http://etherx.jabber.org/streams" 
        xmlns="jabber:client" 
        from="im" 
        id="c997c3a8" 
        xml:lang="en" 
        version="1.0">
        <stream:features>
            <mechanisms 
            xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
                <mechanism>PLAIN</mechanism>
                <mechanism>ANONYMOUS</mechanism>
                <mechanism>JIVE-SHAREDSECRET</mechanism>
            </mechanisms>
            <bind 
                xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
                <session 
                    xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
    </stream:features>
  • 實(shí)際上到這里客戶(hù)端的登錄已經(jīng)完成了,但是還沒(méi)算成功松捉,接下來(lái)可以開(kāi)始做綁定Socket的操作了
SENT
<iq 
    id='b86j8-4' 
    type='set'>
        <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
        </bind>
</iq>
  • 服務(wù)器返回綁定了JID = c997c3a8的客戶(hù)端
RECV
<iq 
    type="result" 
    id="b86j8-4" 
    to="im/c997c3a8">
    <bind 
            xmlns="urn:ietf:params:xml:ns:xmpp-bind">
        <jid>c997c3a8@im/c997c3a8</jid>
    </bind>
</iq>
  • 客戶(hù)端繼續(xù)請(qǐng)求,開(kāi)啟一個(gè)session
SENT
<iq id='b86j8-6' type='set'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>
  • 這時(shí)服務(wù)器返回
RECV
<iq 
    type="result" 
    id="b86j8-6" 
    to="c997c3a8@im/c997c3a8"/>
  • 到此夹界,整個(gè)登錄流程已經(jīng)成功了,接下來(lái)可以做一些用戶(hù)信息的獲取等操作隘世。

結(jié)尾

本篇帶領(lǐng)大家了解如何利用smack登錄Openfire和XMPP的報(bào)文流程可柿,下一個(gè)章節(jié)將會(huì)帶大家進(jìn)入xmpp的里面鸠踪,看看獲取用戶(hù)信息等具體的操作。

引用

https://download.igniterealtime.org/smack/docs/latest/documentation/gettingstarted.html/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末复斥,一起剝皮案震驚了整個(gè)濱河市营密,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌目锭,老刑警劉巖评汰,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異痢虹,居然都是意外死亡被去,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)世分,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)编振,“玉大人,你說(shuō)我怎么就攤上這事臭埋∽傺耄” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵瓢阴,是天一觀的道長(zhǎng)畅蹂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)荣恐,這世上最難降的妖魔是什么液斜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮叠穆,結(jié)果婚禮上少漆,老公的妹妹穿的比我還像新娘。我一直安慰自己硼被,他們只是感情好示损,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著嚷硫,像睡著了一般检访。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仔掸,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天脆贵,我揣著相機(jī)與錄音,去河邊找鬼起暮。 笑死卖氨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播双泪,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼持搜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼密似!你這毒婦竟也來(lái)了焙矛?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤残腌,失蹤者是張志新(化名)和其女友劉穎村斟,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體抛猫,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蟆盹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了闺金。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逾滥。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖败匹,靈堂內(nèi)的尸體忽然破棺而出寨昙,到底是詐尸還是另有隱情,我是刑警寧澤掀亩,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布舔哪,位于F島的核電站,受9級(jí)特大地震影響槽棍,放射性物質(zhì)發(fā)生泄漏捉蚤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一炼七、第九天 我趴在偏房一處隱蔽的房頂上張望缆巧。 院中可真熱鬧,春花似錦豌拙、人聲如沸陕悬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)墩莫。三九已至,卻和暖如春逞敷,著一層夾襖步出監(jiān)牢的瞬間狂秦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工推捐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裂问,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像堪簿,于是被迫代替她去往敵國(guó)和親痊乾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理椭更,服務(wù)發(fā)現(xiàn)哪审,斷路器,智...
    卡卡羅2017閱讀 134,693評(píng)論 18 139
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測(cè)試 ...
    KeKeMars閱讀 6,339評(píng)論 0 6
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,264評(píng)論 25 707
  • 關(guān)于XMPP最權(quán)威的講解:http://www.jabbercn.org/RFC3920(這個(gè)才是最權(quán)威的虑瀑,下面文...
    隨風(fēng)飄蕩的小逗逼閱讀 1,491評(píng)論 1 5
  • 引言 開(kāi)發(fā)這個(gè)插件的目的是因?yàn)樽罱麭oss一再?gòu)?qiáng)調(diào)紀(jì)律湿滓,不允許使用QQ,不過(guò)作為十幾年Q齡的老用戶(hù)舌狗,早已經(jīng)習(xí)慣了Q...
    Jamling閱讀 601評(píng)論 0 1