Xmpp学习之Android-smack入门指导

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

转载请表明出处:http://www.cnblogs.com/cavalier-/p/6940406.html

快速导航

尴尬TOC目录模板不管用了,那就简单来个目录图片。


在此为后面的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的登录方式,具体笔者也没实践过,欢迎拍砖。
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系统了,相当简单:

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/

Xmpp学习之Android-smack入门指导的更多相关文章

  1. Xmpp学习之Smack发送消息JID变乱码

    Xmpp学习之Smack发送消息JID变乱码 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com/cavalier-/p/6947723 ...

  2. 新手入门指导:Vue 2.0 的建议学习顺序

    起步 1. 扎实的 JavaScript / HTML / CSS 基本功.这是前置条件. 2. 通读官方教程 (guide) 的基础篇.不要用任何构建工具,就只用最简单的 <script> ...

  3. Openfire/XMPP学习之——一个简单的Smack样例

    昨天讲了Openfire的搭建和配置,今天来讲一下Smack.如果对如何搭建和配置Openfire的,可以参考Openfire/XMPP学习之——Openfire的安装.配置. Smack是一个开源, ...

  4. React-Native入门指导之iOS篇 —— 一、准备工作

    React-Native 入门指导系列教程目录 一.准备工作 (已完成) 二.项目介绍与调试 三.CSS样式与Flex布局 四.常用UI控件的使用 五.JSX在React-Native中的应用 六.事 ...

  5. React-Native入门指导之iOS篇

    React-Native 入门指导系列教程目录 一.准备工作 (已完成) 二.项目介绍与调试 三.CSS样式与Flex布局 四.常用UI控件的使用 五.JSX在React-Native中的应用 六.事 ...

  6. 用XMPP实现完整Android聊天项目

    简介 这是一个完整的xmpp的Android的项目服务端使用openfire3.9.3客户端使用Android4.2.2 集成第三方:百度地图sdkasmack.jaruniversal-image- ...

  7. [译]:Xamarin.Android开发入门——Hello,Android Multiscreen深入理解

    原文链接:Hello, Android Multiscreen_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android Multiscreen深入理解. 本 ...

  8. [译]:Xamarin.Android开发入门——Hello,Android深入理解

    返回索引目录 原文链接:Hello, Android_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android深入理解 本部分介绍利用Xamarin开发And ...

  9. [电子书] 《Android编程入门很简单》

    <Android编程入门很简单>是一本与众不同的Android学习读物,是一本化繁为简,把抽象问题具体化,把复杂问题简单化的书.本书避免出现云山雾罩.晦涩难懂的讲解,代之以轻松活泼.由浅入 ...

随机推荐

  1. js继承之原型链方式实现

    温故而知新: 在之前的文章已经重点了解了原型对象,今天就理一理这个原型对象在原型链式的继承中的使用 function a(x,y){this.x=x;this.y=y;} //定义一个函数,当构造函数 ...

  2. MySQL最常用数值函数

    数值函数: 用来处理很多数值方面的运算,使用数值函数,可以免去很多繁杂的判断求值的过程,能够大大提高用户的工作效率. 1.ABS(x):返回 x 的绝对值 mysql> select abs(- ...

  3. Linux基础网络搭建实验

    一.实验目标 利用3台虚拟机,搭建vmnet2和vmnet3两个host-only网络,实现两个网络的互联 二.实验环境   内网 外网 网关 IP 192.168.0.10/24 202.3.4.1 ...

  4. Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析

    Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析 0. 前言 个人认为该知识点阅读Android源代码会不仅容易走进死胡同,并且效果并不好,前脚看完后脚忘记,故进行总结, ...

  5. Linux命令之初出茅庐

    此处讲解常用到的参数选项: ls 是列出文件的意思 ls -a ,查看所有文件包含隐藏文件 ls -l ,查看与文件相关的所有属性信息 ls -i ,查看文件的inode信息 ls -h,按照更为容易 ...

  6. poj3020二分图匹配

    The Global Aerial Research Centre has been allotted the task of building the fifth generation of mob ...

  7. 简单五子棋,没有电脑AI

    刚学了C#委托,做了个五子棋练习,把前台绘制和后台逻辑分开,前台绘制方法用委托传给后台逻辑. 界面好简单... 先看类图 控制类控制整个游戏的逻辑,包括调用棋盘类的属性初始化棋盘.初始化两个棋手.轮流 ...

  8. MySQL开发总结(有点长..耐心看)

    一.理解MySQL基本概念 1.MySQL软件:MySQL实际上就是一软件,是一工具,是关系型数据库管理系统软件 2.MySQL数据库:就是按照数据结构来组织.存储和管理数据的仓库 3.MySQL数据 ...

  9. Object-C iOS纯代码布局 一堆代码可以放这里!

    前言: 最近写的文章都是创业类,好吧,今天好好写写技术类的文章! 不过分享的不是IOS相关的文章,毕竟这几天在速成IOS,看的是object-c,由于速成的很快,好累! 好在现在基本已经入了点门道了, ...

  10. cgroup原理简析:vfs文件系统

    要了解cgroup实现原理,必须先了解下vfs(虚拟文件系统).因为cgroup通过vfs向用户层提供接口,用户层通过挂载,创建目录,读写文件的方式与cgroup交互.因为是介绍cgroup的文章,因 ...