Xmpp学习之Android-smack入门指导

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载请表明出处:http://www.jianshu.com/p/049ef7d049eb

[TOC]
WTF简书不支持 toc 目录模式,简单截图一张。


img-w140
img-w140

在此为后面的smack学习做笔记,以作备忘。
以下是本次采用的Demo环境:

  • Openfire 4.3.8.2
  • smack4.2.1

smack之登录

xmpp首次登录,可以通过自定义的Socket去进行连接服务器,如果你服务器不是配置了非常特殊TLS连接,一般可以是用Smack中的XMPPConnection类建立连接(我推荐通过API中的XMPPConnection去连接,能省去很多复杂的过程),下面我讲一下XMPPConnection的连接配置。

基础配置

XMPPConnection的连接需要通过XMPPTCPConnectionConfiguration.builder()配置你在Openfire设置的配置,代码如下:

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```会拼接在首次建立```Socket```的IQ中的to和from中),HostAddress是你运行服务器的域名或IP地址,Port是你登录的端口,在Openfire中默认是5222端口,但如果你的服务器使用的是Nginx做前置机,那么这里你需要填入你的Nginx配置的端口。  

### 进阶配置
可能看到这里,你会觉得很奇怪,为什么还有个进阶配置,难道Openfire难道登录就是一个普通的Socket登录吗?这样很容易被黑吧,没错,实际上还有进阶配置满足加密连接和自定义的要求,如TLS登录或SSL登录或者压缩通讯,如下例子: 

* 如自定义的TLS登录  
TLS的登录方式,具体笔者也没实践过,欢迎拍砖。

```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())); 

以上的代码需要注意一点是内中的MemorizingTrustManager,他来自于MemorizingTrustManager,而另外一个MemorizingKeyManager是自定义的类,内中的代码其实就是自定义了一个继承自X509TrustManager的类,这里不做深究,如有需要可以联系我。

  • 使用旧的TLS连接
    实际上这里的意思是关闭安全模式,可以通过如下代码关闭安全模式
* 其他的兼容方式  
    实际上就是沿用上面的那个函数```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
  • 开启通讯压缩
    这里的通讯压缩开启后,传输的流量将节省90%
builder.setCompressionEnabled(true);
  • SASL认证
    Openfire服务器默认支持 PLAIN 、ANONYMOUS 、JIVE-SHAREDSECRET,这里我的服务器开启的是 PLAIN ,所以我使用 PLAIN
SASLAuthentication.blacklistSASLMechanism(SASLPlainMechanism.NAME);

登录服务器

通过了上面的配置后,咱们可以登录Openfire系统了,相当简单:

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

如果以上的配置和服务器的自定义不匹配,在建立连接的这一步会抛出异常,具体的异常可以通过对应方案处理,这里不详谈。

登录底层报文通讯简要解析

作为程序猿,难道会使用API够了吗?不,我们继续折腾,下面一起来看一下底层的通讯报文流程。

  • 在建立了Socket后,client会向服务器发出一条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'>
  • 服务器解析到上面的指令后,会返回用于告诉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>
  • 客户端选择ANONYMOUS认证方式
SENT
<auth 
    xmlns='urn:ietf:params:xml:ns:xmpp-sasl'    
    mechanism='ANONYMOUS'>=</auth>
  • 服务器通过计算加密后的密码后,服务器将返回
RECV
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
  • 当客户端收到以上命令后,将首次发起连接的id发送到服务器
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'>
  • 这时服务器会返回如下内容说明此时的已经成功绑定了当前的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>
  • 客户端在接收到如上的内容后会告诉服务器开启压缩
SENT
<compress xmlns='http://jabber.org/protocol/compress'><method>zlib</method></compress>
  • 服务器返回
RECV
<compressed xmlns='http://jabber.org/protocol/compress'/>
  • 客户端收到服务器的响应命令后,重新建立一个Socket,发送指令
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'>
  • 服务器将返回,不知道你有没有发现,这里的id="c997c3a8"还是那个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>
  • 实际上到这里客户端的登录已经完成了,但是还没算成功,接下来可以开始做绑定Socket的操作了
SENT
<iq 
    id='b86j8-4' 
    type='set'>
        <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
        </bind>
</iq>
  • 服务器返回绑定了JID = c997c3a8的客户端
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>
  • 客户端继续请求,开启一个session
SENT
<iq id='b86j8-6' type='set'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>
  • 这时服务器返回
RECV
<iq 
    type="result" 
    id="b86j8-6" 
    to="c997c3a8@im/c997c3a8"/>
  • 到此,整个登录流程已经成功了,接下来可以做一些用户信息的获取等操作。

结尾

本篇带领大家了解如何利用smack登录Openfire和XMPP的报文流程,下一个章节将会带大家进入xmpp的里面,看看获取用户信息等具体的操作。

引用

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,183评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,850评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,766评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,854评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,871评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,457评论 1 311
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,999评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,914评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,465评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,543评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,675评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,354评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,029评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,514评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,616评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,091评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,685评论 2 360

推荐阅读更多精彩内容