转载自 https://www.cnblogs.com/jiyuqi/p/5085932.html
IM(Instant Messaging)正在被广泛使用,特别是公司与它们的客户互动连接方案以及互联网与Web2.0相关的应用。为了解决即时通信的标准问题,IETF(互联网工程任务组 The Internet Engineering Task Force)成立了专门的小组、研究和开发IM相关协议。
空间和即时信息协议(Presence and Instant Messaging)
该协议是IETF撰写的关于即时通讯标准协议的早期版本,其抽象模型最早是在2000年2月份提出的RFC2778中提出的。
从2001年起,该项目无任何进展。现在SIP协议以及其衍生出的SIMPLE以及XMPP协议才被认为是即时消息协议的标准实现。
具体参考:
https://en.wikipedia.org/wiki/Presence_and_Instant_Messaging
即时信息与空间协议(Instant Messaging and Presence Protocal)
IMPP主要定义必要的协议和数据格式,用来构件一个具有空间接收、发布能力的即时消息系统。到目前为止,IETF已经出了三个草案的RFC,但主要有两个:一个是针对站点空间和即时通讯模型的(RFC 2778);另一个是针对即时通讯/空间协议需求条件的(RFC2779)。RFC2778是一个资料性质的草案,定义了所有presence和IM服务的原理。RFC2779定义了IMPP的最小需求条件。另外,这个草案还就presence服务定义了一些条款,例如运行的命令、信息的格式、以及presence服务器如何把presence的状态变化通知给客户。
具体参考:
https://en.wikipedia.org/w/index.php?title=Instant_Messaging_and_Presence_Protocol&redirect=no
SIP一种用于信令和控制多媒体通讯session的协议。其最常见的应用是通过SIP协议实现的语音和视频网络电话,以及通过IP网络实现的即时消息通讯。该协议规定了在各通信方中传递的消息,这些消息决定这一个网络电话的建立、终止以及其他必要的步骤。SIP协议可以用于创建、修改和终止一个或多个媒体连接。SIP是一个应用层协议,被设计为独立于下层的传输层。它是一个基于文本的协议,结合了很多HTTP和SMTP协议的元素。SIP协议通常与其他应用层协议一起工作。
SIMPLE协议是由IETF定义的基于SIP的一个即时消息(IM)和空间协议套。与现今广泛使用的软件实现即时通信与空间协议相比,SIMPLE是类似于XMPP的公开标准。
SIMPLE使用SIP协议发送presence信息。SIP是IETF为终端定制的一种协议,其一般用于建立语音通话中,一旦建立连接后,使用实时协议(RTP)进行实际上的语音发送。但SIP不仅可以用在语音上,也可以用在视频上。SIMPLE被定义为一个建立IM进程的方法。
可扩展的消息与空间协议(Extensible Messaging and Presence Protocol)
该协议的前身是Jabber,我们采取XMPP协议主来实现IM主要是考虑XMPP协议是以XML为基础的,它继承了在XML环境中灵活的发展性。这表明XMPP是可扩展的,所以XMPP信息不仅可以是简单的文本,而且可以携带复杂的数据和各种格式的文件,也就是说XMPP协议不仅可以用在人与人之间的交流,而且可以实现软件与软件或软件与人之间的交流,目前支持XMPP协议的即时通讯工具有Gtalk、FaceBook IM、Twitter、网易POPO等等通讯工具。
在以上四种协议中,XMPP协议是最为灵活的,XMPP协议基于XML,因此具有良好的扩展性,经过扩展后的XML协议可以发送扩展信息处理用户的需求,以及在XMPP顶端建立如内容发布系统和基于地址的服务等应用程序。而且XMPP包含了针对服务器的软件协议,使之能与另外一个通话,这使得开发者更容易建立客户应用程序或给一个配置好的系统添加功能。
另外,XMPP协议在业界已有成熟的开源实现方案,从开发成本上来讲也是很有优势的。
开源实现已经实现了客户端和服务器端的协议解析逻辑。用户只需要在此基础上开发自己的业务就可以了。
1. 推送数据
HTTP只能从服务器哪里请求数据,除非服务器正在响应客户端请求,否则不能向客户端发送数据。但XMPP连接是双向的,任何一方在任何时候都可以向另外一方发送数据,只要连接是打开状态。
2. 防火墙友好
XMPP对防火墙和NAT友好,因为服务器到客户端的连接是由客户端发起的,一旦连接,服务器就可以将其所需要的数据推送给客户端。
3. 增强的安全性
XMPP构建在TLS和SASL上,具有更好的安全性
4. 更加丰富的工具箱
XMPP支持更多的操作
1. XMPP是有状态协议
2. XMPP的生态系统较小
3. XMPP有更大的开销
XMPP未对短期会话和简单请求进行优化,建立、维护和销毁XMPP都需要一些资源。
对于更长的连接和更加复杂的交互,XMPP和HTTP的开销可以忽略不计。
主流浏览器暂时没有支持XMPP协议,但是可以通过设置和编程在HTTP连接上建立高效的XMPP会话通道。
这种通道的建立使用到了名为HTTP长连接的技术。通过联合使用一个简单的基于HTTP的管理协议以及XMPP连接管理器,我们可以将XMPP(所有功能)带入到HTTP应用程序中。
是早期定时刷新网页获取数据更新的方法改进,服务端通过维持一个空连接,即时通知客户端数据变更。
因为每个请求均可以持续较长时间,因此称为长轮询。
人们已经设计了多个库和协议来利用长轮询技术,XMPP是其中一个较早实现,在XMPP中,这种桥接被称为BOSH(Bidirection stream Over Synchronous HTTP,在同步HTTP上传递双向数据流)。
XMPP连接可以持续相当长的时间,但HTTP请求确相当短。连接管理器负责维护第三方的XMPP连接并通过HTTP长连接技术提供对连接的访问。
浏览器和连接管理器都使用BOSH协议通过HTTP通信,并提供了安全功能,连接管理器与服务端通信就像一个普通的客户端一样,延时也比较低。
而且连接管理器还有如下的优势:
客户端可以切换网络
托管稳固,可以容忍故障
可好性好,连接管理器缓存数据
对防火墙友好(运行与HTTP端口)
通过Javascript的Strophe库来实现,可以隐藏底层细节并具有很好的效率。
浏览器平台
可以选用jQuery操作用户数据及用户界面。
XMPP服务器
可以选用Tigese或者OpenFire
协议扩展
如果有扩展协议的需求,应该首先试着组合现有协议或者将协议设计的尽量简洁。
服务器 |
许可证 |
操作系统 |
是否支持任意客户端登录 |
备注 |
ejabberd |
开源 |
Elang |
是 |
支持虚拟主机和集群 |
Openfire |
Apache |
Java |
是 |
|
Tigase |
GPLv3 |
Java |
是 |
支持虚拟主机和集群 |
Spark
使用Java开发,具备跨平台性
strophe.js
现决定使用Openfire作为服务端,Openfire采用Java开发,基于XMPP的实时开源协作服务器。单台可支持上万并发用户。
Openfire体系由其提供的服务器端、客户端以及相应的开发库组成。
通常我们所说的Openfire就是指Openfire服务端,现在已经更新到3.10.3版本,该服务器实现了绝大部分的XMPP协议。
除此之外,还有大量的Openfire插件可供使用。
Spark是一个使用java开发的实时协作客户端,通过简单的配置和注册即可使用。
Smack is a client library. You can use it to log into an XMPP domain and make use of the functionality it provides. Typically, Smack is used to implement an instant messaging client。
Tinder is a low-level XMPP library. It provides Java implementations of basic XMPP entities, such as Stanzas (called 'Packet' in XMPP), JIDs and Components (which typically implement part of the functionality of an XMPP server). Although in theory, Tinder could be used to implement client functionality, it currently is primarily used on the server-side. Both Whack and Openfire (an XMPP server implementation) use Tinder-defined entities. Smack does not use Tinder at all.
Whack is Java library that is used to implement external components. Whack allows a Component (as defined in Tinder) to run as a stand-alone process. Whack allows you to connect this process to an XMPP domain. This way, you can extend the functionality provided by that domain without modifying the implementation of the server software.
1. 安装客户端
rmp –ivh MySQL-client-5.6.21-1.linux_glibc2.5.x86_64.rpm
(注)如果提示冲突,需要运行yum –y remove ${APP}卸载冲突软件
2. 安装服务端
rmp –ivh MySQL-server-5.6.21-1.linux_glibc2.5.x86_64.rpm
3. 数据库配置
3.1设置本地登录账号
mysql –u root -p
set password for root@localhost=password('jiyq');
如果主机名其他,例如jiyq,需要将localhost改为jiyq
set password for root@jiyq=password('jiyq');
3.2切换数据库
use mysql;
3.3设置网络连接账户
Grant all privileges on *.* to 'root'@'%' identified by 'jiyq' with grant option;
3.4 更新账户权限
FLUSH PRIVILEGES;
3.5 打开防火墙3306端口
iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 3306 -j ACCEPT
service iptables save
3.7 创建数据库
create database openfire
3.8 运行建表语句
在openfire数据库下,运行/opt/openfire/resources/database/openfire_mysql.sql
1. 解压openfire_3_10_3.zip到/opt目录下
2. 启动openfire
/opt/openfire/bin
./openfire start
3. 访问配置页面
http://192.168.189.131:9090/setup/index.jsp
4. 配置语言
5. 服务器设置
6. 数据库设置
7. 数据库设置-标准连接
8. 特性设置
9. 管理员账户
8. 安装完成
这里使用Spark作为PC端的客户端。
1. 安装Spark
这里采用spark_2_7_3_online.exe版本
2. 注册用户2个用户
3. 登录客户端,并互添加好友
package com.song.controller;
import org.apache.commons.lang.StringUtils;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.chat.Chat;
import org.jivesoftware.smack.chat.ChatManager;
import org.jivesoftware.smack.chat.ChatManagerListener;
import org.jivesoftware.smack.chat.ChatMessageListener;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
/**
* Created by huang(jy) on 2018/3/20.
*/
public class SmackClict {
public static void main(String[] args) {
try {
String serviceName = "192.168.20.125"; //openfire服务器名称
String host = "192.168.20.125"; //openfire服务器地址
int port = 5222; //客户端到服务器,默认5222
String myUsername = "zyy"; //帐号
String myPassword = "123456"; //密码
String friendUsername = "huang"; //要发消息的对象名称
XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder();
builder.setUsernameAndPassword(myUsername, myPassword);
builder.setServiceName(serviceName);
builder.setHost(host);
builder.setPort(port);
builder.setSecurityMode(SecurityMode.disabled);
builder.setDebuggerEnabled(false);
XMPPTCPConnectionConfiguration config = builder.build();
AbstractXMPPConnection c = new XMPPTCPConnection(config);
c.connect();
c.login();
System.out.println("Authenticated = " + c.isAuthenticated());
ChatManager chatmanager = ChatManager.getInstanceFor(c);
Chat newChat = chatmanager.createChat(friendUsername + "@" + serviceName);
final ChatMessageListener messageListener = new ChatMessageListener() {
@Override
public void processMessage(Chat arg0, Message message) {
String messageBody = message.getBody();
if (StringUtils.isNotBlank(messageBody)) {
try {
arg0.sendMessage("你刚说的是:" + messageBody);
} catch (Exception e) {
}
}
}
};
ChatManagerListener chatManagerListener = new ChatManagerListener() {
@Override
public void chatCreated(Chat chat, boolean arg1) {
chat.addMessageListener(messageListener);
}
};
chatmanager.addChatListener(chatManagerListener);
try {
newChat.sendMessage("我来咯");
} catch (Exception e) {
System.out.println("Error Delivering block");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
刚开始的时候在c.login()处一直报空指针的错,后来查证后是因为少引了个jar,引用jar如下
通过spark登录其中一个帐号,通过自定义代码登录另一个帐号
然后给spark客户端帐号发送消息(直接运行main函数),消息发送成功
XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议。在此基础上,XMPP协议已经被用来构建大规模即时通信系统、游戏平台、协作空间及语音和视频会议系统。
XMPP由几个小的构造块组成,并在此基础上扩展出了更多的构造块。XMPP中有众多系统:发布-订阅服务、多人聊天、表单检索与处理、服务发现、实时数据传输、隐私处理及远程过程调用等。
大多数社交媒体(Facebook及Twitter)也采用了XMPP协议。
与其他协议一样,XMPP定义了在两个或者更多通信实体间传递数据所采用的格式。对于XMPP,实体通常是指客户端服务器,但是其也允许客户端与客户端或服务器端与服务器端的通信。
在XMPP上交换的是XML数据,采用这种格式,使XMPP协议获得了极大的可扩展性,因为使用XML可以方便的新增功能并保证前后向兼容。使用XML较二进制协议占用更大的带宽,但获得的优势是具有了几乎无限的可扩展性。
用户可以向XMPP Standards Foundation注册协议扩展。
在XMPP中,XML数据被组织为了一对流,每个流分别对应通信的一个方向。每个XML流均由一个开始元素、后跟XMPP节和其他顶级元素,然后是一个结束元素组成。每个XMPP节(可带有子元素及属性)均是该流的一级子元素。在XMPP连接末尾,这两个流形成了一对有效的XMPP文档。
XMPP节构成了该协议的核心部分,而XMPP应用程序则关注如何发送和响应各种类型的节。节可能包含网络上其他实体的信息、类似于电子邮件的个人消息或为计算机处理而设计的结构化数据。
what think you of books
在一个典型的XMPP会话中,一个上述的节将会从darcy的XMPP客户端发送到她的XMPP服务器,她的服务器将会注意到该节的目的地是某个远程服务器上的一个实体,因此与该远程服务器先建立XMPP连接,并将消息转发该处。
这种通信网络与电子邮件类似,但与电子邮件服务器不同的是,XMPP间的服务器可以直接通信,而不需要借助中间服务器。
这种直接通信避免了垃圾信息的干扰,且还支持通过TLS(Transport Layer Security,传输层安全)来加密通信并通过SASL(Simple Authentication and Security Layers,简单身份验证与安全层)实现身份验证机制。
XMPP使用传递短小信息来设计的,而非针对大型数据块,但XMPP能够用来协商并建立可在端点间传递大型数据块的带内或者带外传输。
最初各大公司发布的ICQ均基于其公司运营的专有协议和网络(ICQ,Yahoo Pager)。
开发人员企图互通这些IM的努力由于协议的闭源特性失败了。
1991年1月Jeremie Miller发布了Jabber项目,Jabber是基于XML的去中心化的即时通信协议,同时也是一个叫jabberd的服务器实现。
2000年5月,Jabber的核心协议稳定,jabberd也正式发布了。
2001年,JSF(Jabber Software Foundation,Jabber软件基金会)成立,并开始围绕jabber协议做规范性工作。
2002年12月,JSF向IETF提交了核心规范,并成立了一个IETF小组。
2004年10月,这个标准化进程产生了Jabber协议的改进版,改名为XMPP,其文档成为RFC标准,编号分别为3920、3921、3922和3923。
最初开发人员向JSF提交的扩展称为JEP(Jabber Extension Proposal,Jabber扩展提议)。最终随着Jabber过度到XMPP,JSF更名为XSF(XMPP Standard Foundation,XMPP标准基金会)和XEP(XMPP Extension Proposal,XMPP扩展提议)。
2005年XMPP技术开始大规模部署,例如Google Talk。
先进有大约300个XEP,并有数十种客户端和服务端实现,开源及商用均有,实际上,任何编程语言都可以找到这样一个库来加速XMPP开发进程。
任何XMPP网络都是由若干角色组成,可以分为服务器端、客户端、组件和服务器插件。
XMPP网络与WWW网络及EMAIL网络不同,XMPP服务器之间寻址只会跳一次,而EMAIL协议则会有多个中转服务器,XMPP保存完整的列表。
XMPP服务器是任何XMPP网络的通信系统,服务器的任务就是为XMPP节提供路由。无论这些节是从内部的一个用户发往另外一个用户还是本地用户发送给服务器。
一组能够相互通信的XMPP服务器构成了XMPP网络。
XMPP服务器总是允许用户连接到自己,但是也可以编写直接使用服务器-服务器协议的应用和程序,来减轻路由消耗。
Ejabberd、Openfire和Tigase是三种能够运行在Windows,Mac OS X和Linux的开源服务器。
M-Link和Jabber XCP是商用产品。
大多数XMPP实体均是客户端,通过客户端-服务器协议连接到XMPP服务器。
客户端必须向某个地方的XMPP服务器进行身份验证。服务器会将该客户端发送的所有节路由到合适的目的地。
服务器还负责管理客户端会话的其他几个方面,包括花名册及裸地址。
不仅仅是客户端能够连接到XMPP服务器,大多数服务器还支持外部服务器组件。这些组件通过添加某种新服务来增强服务器的行为。这些组件在服务器内有各自的身份和地址,但运行在外部并通过组件协议通信。
组件协议(XEP-0114)可以让开发人员以一种服务器不可知的方式创建服务器扩展,例如多人聊天服务。
组件也需要向XMPP服务器进行身份验证,但要较客户端的完全SASL验证简单,例如口令。
每个组件编程服务器内部一个可单独寻址的实体,在外界看类似于一个子服务器。除了基本节之外,XMPP服务器不会代替已连接组件来管理其他节的路由。
服务器还允许组件在内部自行路由或管理节,因而更为灵活。
许多XMPP服务器还支持使用插件进行扩展,但插件深入到服务器内部,有较高的效率以及最低的通用性。
插件一般是绑定特定类型的服务器的。
XMPP网络上的每个实体都有一个或多个地址(称为JID,jabber identifier)。通常类似于:
[email protected]和[email protected]就是两个JID。
JID由三个部分组成,节点、域和资源,域是必须的,其他两个部分是可选的。
域是实体(服务器、组件或插件)可解析的DNS名称。仅由域组成的JID是有效地址,表示服务器地址。指向域的节将由服务器自身处理,并可能被路由到某个组件或插件。
本地部分通常用来识别域中的一个特定用户,位于@前。本地部分也可以用来识别其他对象,如某个聊天室。
JID的资源部分通常会标识一个特定客户端的XMPP连接。对于XMPP客户端而言,每个连接均被指派一个资源。如[email protected]想要连接他的书法和图书馆则可以通过
[email protected]/study和[email protected]/library来寻址,这样避免了用户在打开多个链接时消息无法找到正确的处理器。主要注意的是,资源部分是区分大小写的。
JID划分为两种类型:
完整JID去除资源部分的地址,客户端的裸JID有些特殊,这是因为服务器自己将处理发往客户端的裸JID节。裸JID可以视为寻址用户的账户,而不是客户端。
最为具体的地址
核心XMPP工具集由三个基本节组成,分别为
XMPP流由两份XML文档组成,通信的每个方向均有一个文档,这些文档有一个根元素
//请求自己的花名册
//通知服务器她已在线并可以访问
I cannot talk of books in a ball-room; my head is always full of something else.
//发送消息
// 声明自己不可访问并关闭
from/to/type/id
from的属性并非由客户端提供,而是服务端进行的标记。
presence提供网络实体的可访问性。用户发出presence节,表明自己上线,这样可以会有更大的概率与别人通信(人们更愿意与在线的人交流),但是我们也不用担心任何人都可以看到自己的在线状态,除非我们订阅了该用户的状态,订阅之后,用户的状态信息会自动发送到订阅者处。
实际上,XMPP的presence节是一个简单的专用的发布-订阅方法。
在IM中,presence体现在花名册(roster)中,花名册保存有JID列表以及用户与这些JID的订阅关系,一旦上线,用户发送presence节,剩下的就由服务器处理了(通知自己在线,以及获取联系人的状态信息)
用于从一个实体向另外一个实体发送消息,并可以传输任何类型的结构化信息,不保证传输可靠性
message是一个非常基础的推模型,message通常用于IM,groupchat,警告和通知等。
message的type有如下几种:
类似于email,发出后不等待回应
用于两个实体间的实时通信
多用户聊天室中使用
用于发送警告或通知
发送错误信息
Who are you?
Query
除了type之外,典型的message节中还包含from、to或者id属性(用于目的追踪)。
to中的JID为消息的接受者,from是发送者的JID,但是from属性并非由客户端提供,而是发送者的服务端提供的,以避免地址模仿。
message节中也可以包含未在XMPP协议中定义的负载,可以用于扩展。
表示Info/Query,为XMPP通信提供请求及响应机制,类似于GET/POST/PUT方法。
IQ只能包含一个payload,并且定义了需要由服务器处理的请求或者动作。相对于message来说,IQ具有更好的可靠性,因其要求收到回应。
IQ中包含有id属性,用于识别服务器发回的响应。
用于请求信息,类似于HTTP Get
提供信息或请求,类似于HTTP POST/PUT
响应请求,类似于HTTP 200
错误信息
例子
具有明确的结构,通常包含原节内容,通用错误信息以及应用程序特有的错误条件和信息(可选)
XMPP协议是基于XML的协议,因此其天生提供了很好的可扩展性。我们可以用XMPP传递各种信息,包括链接、位置信息,Web Service等。
发送XMPP节通常需要建立一个经过身份验证的XMPP会话,包括连接、流的建立、身份验证以及断开连接。
在发送任何节之前,需要建立XMPP流,在XMPP流存在之前,必须建立通往XMPP服务器的连接。
当XMPP客户端或者服务器连接到另外一个XMPP服务器时,首先要查询SRV记录,该记录保存有特定域的服务器列表。查询应答中可以包含多条SRV记录,这样就可以在多个服务器中建立负载均衡连接。
如果没有找到合适的SRV记录,那么程序将试图直接连接到指定域。
一旦建立通过给定XMPP服务器的连接,XMPP流就启动了
向服务器发送
建立XMPP流之后就可以来回发送各种元素
服务器发送
XMPP允许进行TLS(Transport Layer Security,传输层安全)加密,而且大多数客户端默认使用该功能。
一旦服务器通告TLS支持后,客户端就会启动TLS连接并将当前套接字升级为加密套接字而不断开连接。一旦TLS加密确立,就会创建一对新的XMPP流。
XMPP中的身份验证使用SASL(Simple Authentication and Security Layers,简单身份验证与安全层)协议并支持多种身份验证机制(取决于服务器)。
一旦完成身份验证,客户端必须为连接绑定一个资源并启动一个会话,通过
当两台服务器相互连接时,身份验证步骤稍稍不同。
当用户结束XMPP会话后,他们终止会话并断开连接,最优雅的方式是首先发送无效出席信息,然后关闭
在XMPP协议中,我们使用presence来获取用户是否已经上线以及是否可以通信的状态。
为了能够知道自己联系人的状态以及让联系人知道自己的状态,用户上线后需要订阅联系人的状态,联系人也同样需要订阅用户的状态。
通过下面的消息订阅联系人的状态:
当联系人接收/拒绝订阅时,会发送消息的消息体(sucribed/unsubscribe)回应。
通常客户端是自动回应这些消息的,当我们订阅了联系人的状态之后,也会受到联系人的状态变更信息。
还可以通过嵌入
away
Having a spot of tea
需要注意的是presence节是占用带宽最多的节,任何对该节内容的扩展都需要慎重。
另外,presence还提供priority属性用来标识资源的优先级(-127-128),负数优先级的资源将无法接收消息,除非显式指定,这个特性通常是由服务器实现的。
另外,我们可以通过发送directed presence到其他用户,来避免订阅对方信息,非常适合应用于网络而上的简短交流。
可以通过发送
presence也有其富文本形式,可以包含更多信息,但不建议在presence中使用(资源和带宽)。Publish-Subscribe[XEP-0060]和Personal Eventing Protocal[XEP-0163]提供了类似功能,但presence是针对整个花名册广播的。
服务器返回的花名册中还可以包含更加丰富的信息,包括用户组以及订阅情况。
用户对花名册的修改也可以通过发送IQ-set(rost-push)同步到服务器及其他客户端上(用户可能有手机/pad等)。这种只推送变更的机制可以简化客户端编程并节省流量。
独立消息,将会马上投递或者缓存,是默认消息类型
用户聊天,通过session建立,通常处理一系列消息
多人聊天,通常此类型会指定一个组件或者模块处理多人聊天,该模块会为每个参与者发送消息
全体通知,不会缓存,立即投递
错误信息节,反馈错误信息
如果用户不在线,则消息被缓存,用户登录后,消息推送给用户,并携带消息原始产生时间,用于客户端对消息进行排序。
可以参考Delayed Delivery[XEP-0203]
chat session用于用户频繁交流的情况,这类似于现实情况中的聊天,其建立过程为:双方用户在消息交互中知道了对方的Full JID,因此可以直接通信,响应的机制称为chat session。
类似于QQ的“正在输入”功能,让交互双方了解即时状态。
该功能扩展由XEP-0085定义。如果用户不希望对方看到自己的状态,可以选择不响应
已经定义好的状态有:Starting,Active,Composing,Paused,Inactive,Gone
消息类似于:
Hi honey!
可以在message消息中加入XHTML用于富文本展示。
协议可以在[XEP-0071]中找到。
I love this movie I saw last night, it's awesome!
I love, this new movie I saw last night, it's awesome!
很容易注意到,消息中包含一个不包含格式的文本,以及XHTML格式的文本,是因为考虑到客户端如果不支持HTML,也可以正常展示。
HTML节中不可以包含HEAD中的信息,也不能包含脚本(安全性考虑)。
也就是虚拟名片,用户在聊天时可以通过虚拟名片查看相关信息。
参考[XEP-0054]
虚拟名片服务通过发送IQ请求查看和更新,但需要注意的是,更新虚拟名片时需要发送完整的信息而不是只有要更新的部分。
查询请求:
返回的消息:
Alice
http://wonderland.lit/~alice/
http://www.cs.cmu.edu/~rgs/alice03a.gif
更新名片:
Alice
http://wonderland.lit/~alice/
http://www.cs.cmu.edu/~rgs/alice03a.gif
[email protected]
类似于QQ可黑名单机制,可以对某人隐身,不看某人的消息或屏蔽某个域的消息等等;当然也包括对名单的修改。
该功能可支持的粒度非常细,参考标准[XEP-0016],[XEP-0191]。
发送一条消息给多个接受者而不通过聊天室
控制消息过期,避免消息被本地存储以及延时投递等
客户端层面确认消息是否已经送达
在服务器上存储消息,而不是在客户端机器上存储
我们需要知道系统中有哪些实体,以及该实体支持哪些服务,为了完成这些操作,引入了实体发现和服务发现的概念。
XMPP 服务发现协议[XEP-0030]定义了两个基本的发现方法。首先发现disco#items,disco#info。
服务发现同样适用iq-get的disco#items/disco#info这两个查询操作,只是将查询是服务而非实体。
具体的查询步骤较为复杂。
Explicit Service Discovery
这种场景应用于用户的花名册向用户返回是否在线的信息,这种判断是否在线的信息带有Full JID,因此可以通过disco#info/disco#item来查询。
但是这种查询可能返回某个Full JID携带的全部信息,导致数据量过大,因此引入了下面的方式。
Entity Capabilites: Service Discovery Shorthand
是对上面方法的改进,通过将实体支持的特性HASH为一组特征吗,客户端接收该特征码后与本地存储进行比较,如果已有该特征码,则可以获得支持的特性列表;如果客户端没有缓冲该特征码,则重新发送disco#info消息获取,并缓存。
采用此种方法可以节省响应的资源。
并且通过presence节就可以获取客户端支持的功能了。
类似于HTML的表单,有工作流的特征,可以实现用户验证码输入和确认等功能。
由[XEP-0004]定义。
3.1 消息在所有的参与者中共享
3.2 所有的参与者都有一个room roster
3.3 参与者都使用其nickname标识,而不是实际的JabberID
3.4 房间共享参与信息
3.5 参与者不仅限于人,也可以是服务等
5.1 用户发送presence消息
5.2 聊天室向成员广播该presence
5.3 聊天室向用户发送成员的presence
5.4 聊天室向用户发送一些历史消息好让用户参与讨论,消息数目可配置,且消息带有时间戳
5.5 之后的聊天消息不再携带时间戳
5.6 聊天室之间的消息往来,消息类型为groupchat
群组中有多重角色,不同的角色拥有不同的权限,可以将用户临时踢出,或加入黑名单等。
具体有:outcast,visitor,participant,member,moderator,admin,owner。
另外房间也有不同的类型,有指定名单的,有临时的,有隐藏的,有固定的等。
用户可以设置其在聊天室内的昵称,参考In-Band Registration[XEP-0077]。
多人聊天可以进行配置,有非常多的可配置项,列出如下。
配置项 |
作用 |
allowinvites |
是否允许普通成员邀请 |
changesubject |
是否非管理员能够更改聊天室主题 |
enablelogging |
是否开启记录归档 |
getmemberlist |
是否能够获取成员列表 |
lang |
语言 |
maxuser |
最大参与者数量 |
membersonly |
是否仅会员可加入(适用于member类型聊天室) |
persistentroom |
房间是否为永久(所有成员退出也不会删除) |
presencebroadcast |
是否广播presence消息,对大room有用 |
publicroom |
该room是否可被发现 |
roomadmin |
设置room管理员 |
roomdesc |
设置room描述 |
roomname |
设置room名称 |
roomowner |
设置room 所有者 |
whois |
控制是否匿名等 |
除了文字之外,MCU还可以传输地理信息,文件和进行远程调用等。
实际上就是消息系统中的推模式,主要分三个步骤完成:首先订阅一个主题;其次发布一个消息;最后消息被推送到订阅客户端。[XEP-0060]
订阅者需要订阅一个源,发布者也将消息发布到这个源。
流程:
如果成功则可以接收消息了,如果失败,则有可能是要求更多的配置信息
主要分为两个部分。
发布方发布消息到源;服务器将源的消息通过message的形式投递给订阅方。
需要注意的是:发布方只负责将消息推送至源,投递的逻辑由订阅方的服务器完成。
用户可以选择是否在通知中携带payloads,如通知中包含头像信息时,只需要metadata,无需具体的数据。
是否启用payload可以通过配置项deliver_payloads来实现。
是否保存items也是可以配置的,可以通过persist_items配置。
保存/不保存数据的node分别称为persistent nodes/transient node。
nodes及其服务可以通过disco#info/disco#item来查询
返回的结果可以通过以上两个命令进一步查询,直到找到想要订阅的node。
如果用户想订阅某个好友的动态,可以使用用户的JID作为datanode,相应的简化协议称为PEP[XEP-0163](Personal Eventing Protocal)。
用户可以应用PEP协议,在自己的Presence消息中包含自己的爱好信息,服务器收到该presence后,将会根据此爱好向用户推送好友的动态。
包括User Tune,User Location,User Activity,User Mood,User Nickname,User Avatar等。