<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.jabbercn.org/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-cn">
		<id>http://wiki.jabbercn.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Terence+lee100</id>
		<title>Jabber/XMPP中文翻译计划 - 用户贡献 [zh-cn]</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.jabbercn.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Terence+lee100"/>
		<link rel="alternate" type="text/html" href="http://wiki.jabbercn.org/%E7%89%B9%E6%AE%8A:%E7%94%A8%E6%88%B7%E8%B4%A1%E7%8C%AE/Terence_lee100"/>
		<updated>2026-04-23T23:24:14Z</updated>
		<subtitle>用户贡献</subtitle>
		<generator>MediaWiki 1.18.2</generator>

	<entry>
		<id>http://wiki.jabbercn.org/RFC6120</id>
		<title>RFC6120</title>
		<link rel="alternate" type="text/html" href="http://wiki.jabbercn.org/RFC6120"/>
				<updated>2012-07-17T01:46:54Z</updated>
		
		<summary type="html">&lt;p&gt;Terence lee100: /* connection-timeout */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:XMPP相关RFC]]&lt;br /&gt;
[[Category:XMPP核心RFC]]&lt;br /&gt;
[[Category:翻译中]]&lt;br /&gt;
&lt;br /&gt;
&amp;quot;本文的英文原文来自[http://xmpp.org/rfcs/rfc6120.html RFC 6120]&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; width=&amp;quot;65%&amp;quot;&lt;br /&gt;
|互联网工程任务组(IETF) || P. Saint-Andre&lt;br /&gt;
|-&lt;br /&gt;
|申请讨论: 6120 || Cisco&lt;br /&gt;
|-&lt;br /&gt;
|取代: 3920 || 2011年3月&lt;br /&gt;
|-&lt;br /&gt;
|类别: 标准跟踪 || &lt;br /&gt;
|-&lt;br /&gt;
|ISSN: 2070-1721 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:::'''可扩展的消息和出席信息协议 (XMPP): 核心协议'''&lt;br /&gt;
&lt;br /&gt;
'''摘要'''&lt;br /&gt;
&lt;br /&gt;
:可扩展的消息和出席信息协议(XMPP)是一个XML应用，让任何两个或多个网络实体之间进行结构化和可扩展的准实时信息交流. 本文定义了XMPP的核心协议方法: XML流的配置和解除, 通道加密, 验证, 错误处理, 以及消息通讯基础, 网络可用性 (&amp;quot;presence&amp;quot;), 和 请求-应答 交互. 本文取代了 RFC 3920.&lt;br /&gt;
&lt;br /&gt;
'''本文的状态'''&lt;br /&gt;
&lt;br /&gt;
:这是一个互联网标准跟踪文档.&lt;br /&gt;
&lt;br /&gt;
:本文是互联网工程工作组(IETF)的一个成果. 它代表了IETF社区的一致意见. 它已经公开审核并由互联网工程控制组(IESG)批准发布了. 更多关于互联网标准的信息请参见RFC 5741第2章.&lt;br /&gt;
&lt;br /&gt;
:关于本文当前状态的信息, 任何错误, 以及如何对它提出反馈，请到 http://www.rfc-editor.org/info/rfc6120 .&lt;br /&gt;
&lt;br /&gt;
'''版权通知'''&lt;br /&gt;
&lt;br /&gt;
:Copyright (c) 2011 IETF Trust and the persons identified as the document authors. All rights reserved.&lt;br /&gt;
&lt;br /&gt;
:This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.&lt;br /&gt;
&lt;br /&gt;
==序论==&lt;br /&gt;
===概述===&lt;br /&gt;
&lt;br /&gt;
可扩展的消息和出席信息协议(XMPP)是一个可扩展标记语言[[RFC6120#XML|XML]]应用，让任何两个或多个网络实体之间进行结构化和可扩展的准实时信息交流. 本文定义了XMPP的核心协议方法: XML流的配置和解除, 通道加密, 验证, 错误处理, 以及消息通讯基础, 网络可用性 (&amp;quot;presence&amp;quot;), 和 请求-应答 交互.&lt;br /&gt;
&lt;br /&gt;
===历史===&lt;br /&gt;
&lt;br /&gt;
XMPP的基本语法和语义最开始是由Jabber开源社区开发的, 主要是在1999年. 2002年, 根据 [[RFC6120#IMP‑REQS|IMP‑REQS]] ，XMPP工作组被允许基于Jabber协议开发一个适合IETF的即时消息和出席信息技术. 到了2004年10月, 发布了 [[RFC3920]] 和 [[RFC3921]] , 意味着那时候XMPP的主要定义完成了.&lt;br /&gt;
&lt;br /&gt;
从2004年开始，互联网社区已经获得了广泛的XMPP实现和布署经验, 包括XMPP标准基金会(XSF)主持下开展的正式的互操作性测试. 本文全面整合了从软件开发者和XMPP服务提供者得到的反馈, 包含了一系列向后兼容的修改，见 [[RFC6120#附录D:和RFC3920的不同|附录D]] . 结果是, 本文反映了互联网社区对于XMPP1.0核心功能的初步共识, 因此废止了RFC 3920.&lt;br /&gt;
&lt;br /&gt;
===功能汇总===&lt;br /&gt;
&lt;br /&gt;
这个不规范的章节提供了一个方便开发者的XMPP功能汇总; 接下来的其他章节则是XMPP的规范定义.&lt;br /&gt;
&lt;br /&gt;
XMPP的目标是允许两个(或多个)实体通过网络来交换相关的小件结构化数据(所谓&amp;quot;XML节&amp;quot;). XMPP典型地使用分布式的 客户端-服务器 体系结构来实现, 这里客户端需要连接到一个服务器以获得对网络的访问，从而被允许和其他实体(可能在其他服务器上)交换XML节. 一个客户端连接到一个服务器，交换XML节，以及结束连接，这样的流程如下: &lt;br /&gt;
&lt;br /&gt;
# 确定要连接的IP地址和端口号, 典型的做法是对一个合格的域名做出解析( [[RFC6120#合格域名的解析|3.2]] )&lt;br /&gt;
# 打开一个传输控制协议 [[RFC6120#TCP|TCP]] 连接&lt;br /&gt;
# 通过TCP打开一个XML流 [[RFC6120#打开一个流|4.2]]&lt;br /&gt;
# 握手最好使用传输层安全性 [[RFC6120#TLS|TLS]] 来进行通道加密( [[RFC6120#STARTTLS握手|5]] )&lt;br /&gt;
# 使用简单验证和安全层 [[RFC6120#SASL|SASL]] 机制来验证 ( [[RFC6120#SASL握手|6]] )&lt;br /&gt;
# 绑定一个资源到这个流上 ( [[RFC6120#资源绑定|7]] )&lt;br /&gt;
# 和其他网络上的实体交换不限数量的XML节( [[RFC6120#XML节|8]] )&lt;br /&gt;
# 关闭XML流 ( [[RFC6120#关闭一个流|4.4]] )&lt;br /&gt;
# 关闭TCP连接&lt;br /&gt;
&lt;br /&gt;
在XMPP中, 一个服务器可以选择性地连接到另一个服务器以激活域间或服务器间的通讯. 这种情形下, 两个服务器需要在他们自身之间建立一个连接然后交换XML节; 这个过程所做的事情如下: &lt;br /&gt;
&lt;br /&gt;
# 确定要连接的IP地址和端口号, 典型的做法是对一个合格的域名做出解析( [[RFC6120#合格域名的解析|3.2]] )&lt;br /&gt;
# 打开一个TCP连接&lt;br /&gt;
# 打开一个XML流 [[RFC6120#打开一个流|4.2]]&lt;br /&gt;
# 握手最好使用TLS来进行通道加密( [[RFC6120#STARTTLS握手|5]] )&lt;br /&gt;
# 使用简单验证和安全层 [[RFC6120#SASL|SASL]] 机制来验证 ( [[RFC6120#SASL握手|6]] ) *&lt;br /&gt;
# 交换不限数量的XML节，可以服务器之间直接交换，也可以代表每台服务器上的相关实体来交换，例如那些连到服务器上的客户端 ( [[RFC6120#XML节|8]] )&lt;br /&gt;
# 关闭XML流 ( [[RFC6120#关闭一个流|4.4]] )&lt;br /&gt;
# 关闭TCP连接&lt;br /&gt;
&lt;br /&gt;
* 互操作性提示: 在本文写就的时候, 大多数已布署的服务器仍使用服务器回拨协议 [[RFC6120#XEP‑0220|XEP‑0220]] 来提供弱身份验证，而不是使用SASL的 PKIX证书来提供强验证, 特别在这些情况下，SASL握手无论如何将不会得到强验证 (例如, 因为TLS握手没有被对方服务器强制要求, 或因为当TLS握手时对方服务器提供的PKIX证书是自签名的并且之前没有被接受过); 细节请见 [[RFC6120#XEP‑0220|XEP‑0220]] . 本文的解决方案显然提供了一个更高级别的安全性 (参见  [[RFC6120#高安全性|13.6]] ).&lt;br /&gt;
&lt;br /&gt;
本文指定了客户端如何连接到服务器以及基本的XML节语义. 然而, 本文不定义一个连接成功建立之后可能用来交换的XML节的&amp;quot;载荷&amp;quot;; 反之, 那些载荷被定义在各种XMPP扩展之中. 例如, [[RFC6120#XMPP‑IM|XMPP‑IM]] 定义了基本的即时消息和出席信息功能的扩展. 另外, XSF创造了各种扩展协议，即XEP系列  [[RFC6120#XEP‑0001|XEP‑0001]] ,也为广泛的应用程序定义了扩展.&lt;br /&gt;
&lt;br /&gt;
===术语===&lt;br /&gt;
&lt;br /&gt;
本文中的关键字 &amp;quot;MUST&amp;quot;, &amp;quot;MUST NOT&amp;quot;, &amp;quot;REQUIRED&amp;quot;, &amp;quot;SHALL&amp;quot;, &amp;quot;SHALL NOT&amp;quot;, &amp;quot;SHOULD&amp;quot;, &amp;quot;SHOULD NOT&amp;quot;, &amp;quot;RECOMMENDED&amp;quot;, &amp;quot;NOT RECOMMENDED&amp;quot;, &amp;quot;MAY&amp;quot;, 和 &amp;quot;OPTIONAL&amp;quot; 的解释参见RFC 2119 [[RFC6120#关键字|关键字]] .&lt;br /&gt;
&lt;br /&gt;
特定的安全相关的术语的含义参见 [[RFC6120#安全术语|安全术语]] ; 这些术语包括但不限于, &amp;quot;assurance&amp;quot;, &amp;quot;attack&amp;quot;, &amp;quot;authentication&amp;quot;, &amp;quot;authorization&amp;quot;, &amp;quot;certificate&amp;quot;, &amp;quot;certification authority&amp;quot;, &amp;quot;certification path&amp;quot;, &amp;quot;confidentiality&amp;quot;, &amp;quot;credential&amp;quot;, &amp;quot;downgrade&amp;quot;, &amp;quot;encryption&amp;quot;, &amp;quot;hash value&amp;quot;, &amp;quot;identity&amp;quot;, &amp;quot;integrity&amp;quot;, &amp;quot;signature&amp;quot;, &amp;quot;self-signed certificate&amp;quot;, &amp;quot;sign&amp;quot;, &amp;quot;spoof&amp;quot;, &amp;quot;tamper&amp;quot;, &amp;quot;trust&amp;quot;, &amp;quot;trust anchor&amp;quot;, &amp;quot;validate&amp;quot;, and &amp;quot;verify&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
特定的和证书，域名，应用服务身份相关的术语参见 [[RFC6120#TLS‑证书|TLS‑证书]] ; 这包括但不限于, &amp;quot;PKIX certificate&amp;quot;, &amp;quot;source domain&amp;quot;, &amp;quot;derived domain&amp;quot;, 以及身份类型 &amp;quot;CN-ID&amp;quot;, &amp;quot;DNS-ID&amp;quot;, 和 &amp;quot;SRV-ID&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
其他安全相关的术语定义于参考协议中 (例如, &amp;quot;denial of service&amp;quot; (拒绝服务)定义于 [[RFC6120#DOS|DOS]] 或 &amp;quot;end entity certificate&amp;quot; (终端实体证书)定义于 [[RFC6120#PKIX|PKIX]] ).&lt;br /&gt;
&lt;br /&gt;
术语 &amp;quot;whitespace&amp;quot; (空格) 用于指代 [[RFC6120#XML|XML]] 中任何匹配&amp;quot;S&amp;quot;的字符或字符串, 也就是说, 一个或多个满足 [[RFC6120#ABNF|ABNF]] 定义的SP, HTAB, CR, 或 LF 规则的实例.&lt;br /&gt;
&lt;br /&gt;
术语 &amp;quot;localpart&amp;quot; (本地部分), &amp;quot;domainpart&amp;quot; (域部分), 以及 &amp;quot;resourcepart&amp;quot; (资源部分)定义于 [[RFC6120#XMPP地址|XMPP地址]] .&lt;br /&gt;
&lt;br /&gt;
术语 &amp;quot;bare JID&amp;quot; (纯JID) 指代一个格式为 &amp;lt;localpart@domainpart&amp;gt; (对于一个位于某个服务器上的帐户而言) 或 &amp;lt;domainpart&amp;gt; (对于一个服务器而言) 的XMPP地址.&lt;br /&gt;
&lt;br /&gt;
术语 &amp;quot;full JID&amp;quot; (全JID) 指代一个格式为 &amp;lt;localpart@domainpart/resourcepart&amp;gt; (对一个典型的已授权客户端或和某个帐号相关的设备而言) 或 &amp;lt;domainpart/resourcepart&amp;gt; (对于一个典型的资源或和某个服务器相关的文字)的XMPP地址.&lt;br /&gt;
&lt;br /&gt;
术语 &amp;quot;XML stream&amp;quot; (也称为 &amp;quot;stream&amp;quot; (流)) 定义于 [[RFC6120#流的基本原理|4.1]] .&lt;br /&gt;
&lt;br /&gt;
术语 &amp;quot;XML stanza&amp;quot; (也称为 &amp;quot;stanza&amp;quot; (节)) 定义于 [[RFC6120#流的基本原理|4.1]] . 有三种 stanzas（节）: message, presence, 和 IQ (&amp;quot;Info/Query&amp;quot;的简称). 这些通讯原语分别定义于 [[RFC6120#Message语义|8.2.1]] , [[RFC6120#Presence语义|8.2.2]] , 和 [[RFC6120#IQ语义|8.2.3]] .&lt;br /&gt;
&lt;br /&gt;
术语 &amp;quot;originating entity&amp;quot; (原实体)指的是第一次生成一个发送到XMPP网络的stanza(节)的实体(例如, 一个已连接的客户端, 一个附加的服务, 或一个服务器). 术语 &amp;quot;generated stanza&amp;quot; (生成的节)值的是生成的节那个节.&lt;br /&gt;
&lt;br /&gt;
术语 &amp;quot;input stream&amp;quot; (输入流)指定这样一个XML流，服务器通过这个流从一个已连接的客户端或远端服务器接收数据, 而术语 &amp;quot;output stream&amp;quot; (输出流)指定这样一个流，服务器通过这个流发送数据到一个已连接的客户端或远程服务器. 以下术语指定一些动作，处理从输入流收到的数据时服务器可以执行这些动作:&lt;br /&gt;
&lt;br /&gt;
        route(路由):&lt;br /&gt;
            传递数据到一个远端服务器让它自行处理或最终递送到一个和远端服务器关联的客户端&lt;br /&gt;
        deliver(递送):&lt;br /&gt;
            传递数据到一个已连接的客户端&lt;br /&gt;
        ignore(忽略):&lt;br /&gt;
            丢弃数据不做任何处理或返回一个错误给发送者sender &lt;br /&gt;
&lt;br /&gt;
当术语 &amp;quot;ignore&amp;quot; (忽略)用于客户端处理收到的数据时, 短语 &amp;quot;without acting upon it&amp;quot; (不做任何处理)明确的包括不展示任何数据给使用者(人).&lt;br /&gt;
&lt;br /&gt;
接下来的 &amp;quot;XML符号&amp;quot; 被 [[RFC6120#IRI|IRI]] 用于展示无法用仅用ASCII码呈现的字符, 本文的一些例子使用了类似 &amp;quot;&amp;amp;#x....&amp;quot; 的格式来表现 [[RFC6120#UNICODE|UNICODE]] 字符串 (例如, 字符串 &amp;quot;&amp;amp;#x0159;&amp;quot; 表示Unicode字符 LATIN SMALL LETTER R WITH CARON); 这种形式是绝对不会在XMPP系统将通过网络发送的.&lt;br /&gt;
&lt;br /&gt;
和 [[RFC6120#URI|URI]] 展现统一资源定位符的规则一样, XMPP地址文本也是用 '&amp;lt;' 和 '&amp;gt;' 括起来的(尽管基本上它们不属于 URIs).&lt;br /&gt;
&lt;br /&gt;
例如, 被括起来的行是用来提高可读性的, &amp;quot;[...]&amp;quot; 表示省略, 并且还是用了以下预定义字符串 (这些预定义的字符串不会通过网络发送出去):&lt;br /&gt;
&lt;br /&gt;
* C: = 客户端&lt;br /&gt;
* E: = 任何XMPP实体&lt;br /&gt;
* I: = 发起实体&lt;br /&gt;
* P: = 对端服务器&lt;br /&gt;
* R: = 接收实体&lt;br /&gt;
* S: = 服务器&lt;br /&gt;
* S1: = 服务器1&lt;br /&gt;
* S2: = 服务器2&lt;br /&gt;
&lt;br /&gt;
读者需要注意这些例子不包括细节, 并且例子里的一些协议流程中, 展示的备用步骤不一定是由前一个步骤发送的确切的数据触发的; 本文或常用参考文档中的协议规范所用到的所有用例里面提供的例子都遵从上述规则. 所有例子都是虚构的并且交换的信息 (例如, 用户名和密码) 不代表任何现存的用户和服务器.&lt;br /&gt;
&lt;br /&gt;
==体系结构==&lt;br /&gt;
&lt;br /&gt;
XMPP提供一种异步的端到端的结构化数据交换技术，在一个分布式的可全球寻址和出席信息感知的客户端和服务器的网络中使用直接的持久XML流。这种体系结构形式包含了普遍的网络可用性的知识，以及在给定的客户端-服务器和服务器-服务器会话的时候，不限数量的并发信息交易的概念，所以我们把它称为 &amp;quot;并发交易可用性&amp;quot; (&amp;quot;Availability for Concurrent Transactions&amp;quot;) (简称ACT) 来把它和来自WWW的 &amp;quot;Representational State Transfer&amp;quot; [[RFC6120#REST|REST]] 体系结构形式区别开. 尽管XMPP的体系结构很大程度上类似于 email (参见 [[RFC6120#EMAIL‑ARCH|EMAIL‑ARCH]], 它引入了一些变化以便于准实时通讯.  ACT体系结构形式的独特特性如下. &lt;br /&gt;
&lt;br /&gt;
===全局地址===&lt;br /&gt;
&lt;br /&gt;
和email一样, 为了通过网络路由和递送消息,XMPP使用全球唯一地址(基于DNS). 所有XMPP实体可以在网络上被寻址, 大部分客户端和服务器以及很多外部服务可以被客户端和服务器访问. 通常, 服务器地址的格式为 &amp;lt;域部分&amp;gt; (例如, &amp;lt;im.example.com&amp;gt;), 属于某台服务器的帐号的格式为 &amp;lt;本地部分@域部分&amp;gt; (例如, &amp;lt;juliet@im.example.com&amp;gt;, 称为 &amp;quot;纯JID&amp;quot;), 而连接到一个特定的设备或资源并且已经被(服务器)授权可以和外部交互的客户端的格式为 &amp;lt;本地部分@域部分/资源部分&amp;gt; (例如, &amp;lt;juliet@im.example.com/balcony&amp;gt;, 称为 &amp;quot;全JID&amp;quot;). 因为历史原因, XMPP地址常被称为Jabber IDs 或 JIDs. 因为XMPP地址格式的正式规范依赖于国际化技术（本文撰写时正在制定中），这个格式定义于 [[RFC6120#XMPP‑ADDR|XMPP‑ADDR]] 而非本文之中. 术语 &amp;quot;localpart&amp;quot;(本地部分), &amp;quot;domainpart&amp;quot;（域部分）, 和 &amp;quot;resourcepart&amp;quot;（资源部分） 正式定义于  [[RFC6120#XMPP‑ADDR|XMPP‑ADDR]] .&lt;br /&gt;
&lt;br /&gt;
===出席信息===&lt;br /&gt;
&lt;br /&gt;
XMPP让一个实体能够向其他实体声明它的网络可用性或者 &amp;quot;presence&amp;quot;（出席信息） . 在XMPP中, 这种可通讯状态是用端到端的专用通讯元素来标识的: 即 &amp;lt;presence/&amp;gt; 节. 尽管网络可用性对于XMPP消息交换并不是必需的, 它还是可以促进实时交互，因为消息发起者可以在发消息之前知道接收者在线并处于可通讯状态. 端到端的出席信息定义于 [[RFC6120#XMPP‑IM|XMPP‑IM]] .&lt;br /&gt;
&lt;br /&gt;
===持久流===&lt;br /&gt;
&lt;br /&gt;
每个点对点的一&amp;quot;跳&amp;quot;都建立了基于TCP长连接的持久XML流来保持可通讯状态. 这些 &amp;quot;always-on&amp;quot; 客户端-服务器 和 服务器-服务器 流使得任何时间每方都能够推送数据到另一方并且立即路由和递送. XML流定义于 [[RFC6120#XML流|4]] .&lt;br /&gt;
&lt;br /&gt;
===结构化数据===&lt;br /&gt;
&lt;br /&gt;
XMPP中基本的协议数据单元不是一个XML流 (它只是为点对点通讯提供传输层) 而是一个 XML 节（&amp;quot;stanza&amp;quot;), 它是一个通过流发送的XML片段. 一个节的根元素包括路由属性 (类似 &amp;quot;from&amp;quot; 和 &amp;quot;to&amp;quot; 地址), 而节的子元素包含了递送给目标接收者的载荷. XML节定义于 [[RFC6120#XML节|8]] .&lt;br /&gt;
&lt;br /&gt;
===客户端和服务器的分布式网络===&lt;br /&gt;
&lt;br /&gt;
在实践之中, XMPP是一个包含了很多互相通讯的客户端和服务器的网络(当然, 任何两个给定的布署服务器之间的通讯都是严格谨慎的并且也和本地服务策略有关). 因此, 例如, 与服务器 &amp;lt;im.example.com&amp;gt; 关联的用户 &amp;lt;juliet@im.example.com&amp;gt; 能够和服务器 &amp;lt;example.net&amp;gt; 关联的用户 &amp;lt;romeo@example.net&amp;gt; 交换消息，出席信息和其他结构化数据. 这个模式对使用全局地址的消息协议是很常见的, 例如email网络 (见 [[RFC6120#SMTP|SMTP]] 和 [[RFC6120#EMAIL‑ARCH|EMAIL‑ARCH]] . 结果, 在XMPP中端到端的通讯是逻辑上的点对点，而物理结构则是 客户端-服务器-服务器-客户端, 如下图所示. &lt;br /&gt;
&lt;br /&gt;
'''图1: 分布式客户端-服务器 体系结构'''&lt;br /&gt;
&lt;br /&gt;
  example.net &amp;lt;--------------&amp;gt; im.example.com&lt;br /&gt;
      ^                                ^&lt;br /&gt;
      |                                |&lt;br /&gt;
      v                                v&lt;br /&gt;
 romeo@example.net           juliet@im.example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 体系结构使用 [[RFC6120#XML流|XML流]] 和 [[RFC6120#XML节|XML节]] ，但是两个客户端之间直接建立端到端的连接则使用基于 [[RFC6120#LINKLOCAL|LINKLOCAL]] 的技术, 不过那个体系结构没有定义在本协议之中，它只能说是 &amp;quot;类XMPP&amp;quot;; 详见 [[RFC6120#XEP‑0174|XEP‑0174]] . 另外, XML流可以在任何可靠的传输层上建立端到端的连接, 包括XMPP本身的扩展; 无论如何, 这些方法没有包含在本文之中.&lt;br /&gt;
&lt;br /&gt;
以下段落描述客户端和服务器们各自在网络中负责什么.&lt;br /&gt;
&lt;br /&gt;
一个客户端就是一个实体，它先和它的注册帐号所在服务器建立XML流 (通过 [[RFC6120#SASL握手|SASL握手]] ) , 然后完成 [[RFC6120#资源绑定|资源绑定]] , 这样就能通过建好的流在客户端和服务器之间递送XML节. 客户端使用 XMPP 来和它的服务器, 其他客户端以及任何其他网络上的实体通讯, 这里服务器负责递送节到同一台服务器上其他已连接的客户端，或把它们路由到远程服务器上. 一个服务器上的注册帐号可以同时使用多个客户端连接到一台服务器上, 这里每个客户端的XMPP地址的 ''资源部分'' 是不同的 (例如, &amp;lt;juliet@im.example.com/balcony&amp;gt; 和 &amp;lt;juliet@im.example.com/chamber&amp;gt;), 定义于 [[RFC6120#常规引用|XMPP‑ADDR]] 和 [[RFC6120#资源绑定|7]]&lt;br /&gt;
&lt;br /&gt;
一个服务器是一个实体，主要负责以下事项: &lt;br /&gt;
&lt;br /&gt;
:* 管理已连接客户端的 [[RFC6120#XML流|XML流]] 并通过建好的流递送 [[RFC6120#XML节|XML节]] 到那些通过客户端; 这也包括负责确保客户端在被授权访问XMPP网络之前的客户端身份验证工作.&lt;br /&gt;
:* 遵循本地服务对服务器之间通讯的策略, 管理和远程服务器之间的 [[RFC6120#XML流|XML流]] 并通过建好的流路由 [[RFC6120#XML节|XML节]] 到那些服务器.&lt;br /&gt;
&lt;br /&gt;
取决于服务器的不同, 一个XMPP服务器的次要责任可能包括: &lt;br /&gt;
&lt;br /&gt;
:* 存储客户端使用的数据 (例如, 用户的基于 [[RFC6120#常规引用|XMPP-IM]] 的联系人; 在这种情况下, 相关的XML节直接由服务器本身代替客户端来处理而不用路由到远程服务器或递送到一个已连接的客户端.&lt;br /&gt;
:* 托管的额外服务也使用XMPP作为通讯的基础，但是提供超出本文范围的额外的或 [[RFC6120#常规引用|XMPP-IM]] 定义的功能; 例子包括多用户会议服务(定义于 [[RFC6120#常规引用|XEP‑0045]] ) 和 发布-订阅 服务 (定义于 [[RFC6120#常规引用|XEP‑0060]] ).&lt;br /&gt;
&lt;br /&gt;
==TCP绑定==&lt;br /&gt;
===范围===&lt;br /&gt;
&lt;br /&gt;
如本文定义的XMPP所述, 一个发起方实体在 (客户端或服务器) 和接收方实体协商XML流之前必须(MUST) 打开一个到接收方实体 (服务器) 的 [[RFC6120#常规引用|TCP]] 连接. 然后在使用XML流期间双方一直保持那个TCP连接. 这个规则在下面章节中的TCP绑定要用到.&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 不一定要把XML流建立在TCP上, 其他传输协议也是可以的. 例如, 两个实体可以通过 [[RFC6120#提示性引用|HTTP]] 互相连接（定义于 [[RFC6120#提示性引用|XEP‑0124]] 和 [[RFC6120#提示性引用|XEP‑0206]] . 无论如何, 本协议只定义把XMPP绑定到TCP.&lt;br /&gt;
&lt;br /&gt;
===合格的全域名解析===&lt;br /&gt;
&lt;br /&gt;
因为XML流是是通过TCP发送的, 发起方实体在尝试打开一个XML流之前需要确定接收方实体的IPv4或IPv6地址(以及端口). 一般来说这是通过解析接收方实体的合格的全域名(简称FQDN,参见 [[RFC6120#常规引用|DNS概念]] )来实现的. &lt;br /&gt;
&lt;br /&gt;
====首选流程:SRV查询====&lt;br /&gt;
&lt;br /&gt;
FQDN解析的首选流程是如下使用 [[RFC6120#常规引用|DNS‑SRV]] 记录: &lt;br /&gt;
&lt;br /&gt;
# 发起方实体构造一个 DNS SRV 查询，参数如下:&lt;br /&gt;
## 一个 &amp;quot;xmpp-client&amp;quot; (用于 客户端-服务器 连接) 或 &amp;quot;xmpp-server&amp;quot; (用于 服务器-服务器 连接)服务&lt;br /&gt;
## 一个 &amp;quot;tcp&amp;quot; 协议&lt;br /&gt;
## 一个对应发起方实体希望连接的XMPP服务的 &amp;quot;原有域&amp;quot;（ [[RFC6120#常规引用|TLS‑CERTS]] ）的名字 (例如, &amp;quot;example.net&amp;quot; 或 &amp;quot;im.example.com&amp;quot;)&lt;br /&gt;
# 得到一个类似 &amp;quot;_xmpp-client._tcp.example.net.&amp;quot; 或 &amp;quot;_xmpp-server._tcp.im.example.com.&amp;quot; 的查询.&lt;br /&gt;
# 如果收到应答, 它将包含一个或多个FDQN和端口的组合, 每个都拥有权重和优先级 (如 [[RFC6120#常规引用|DNS‑SRV]] 所述). (无论如何, 如果SRV查询的结果是一个单独的资源记录 &amp;quot;.&amp;quot;, 即根域名, 那么发起方实体必须(MUST)在这时终止SRV处理，因为根据 [[RFC6120#常规引用|DNS‑SRV]] ,这样一个结果意味着那个服务在本域中是不可用的)&lt;br /&gt;
# 发起方实体至少选择返回的FQDNs记录中的一个来解决 (根据 [[RFC6120#常规引用|DNS‑SRV]] 规则,对FDQN执行 DNS &amp;quot;A&amp;quot; 或 &amp;quot;AAAA&amp;quot; 查询; 这将返回一个 IPv4 或 IPv6 的地址.&lt;br /&gt;
# 成功解析FDQN(包括SRV查询返回的相应的端口号)之后,发起方实体就使用IP地址来连接接收方实体.&lt;br /&gt;
# 如果发起方实体使用那个IP地址连接失败，而的 &amp;quot;A&amp;quot; 或 &amp;quot;AAAA&amp;quot; 记录查询返回了不止一个IP地址, 那么发起方实体使用那个FDQN的下一个解析好的IP地址作为连接地址.&lt;br /&gt;
# 如果发起方实体用给定的FDQN的所有解析出来的IP地址都无法连接, 那么它重复解析过程并使用基于优先级和权重的SRV查询(定义于 [[RFC6120#常规引用|DNS SRV]] )返回的下一个FQDN来连接.&lt;br /&gt;
# 如果发起方实体接收到它的SRV应答但是无法使用接收到的应答数据来建立一个XMPP连接, 它不应该(SHOULD NOT)尝试下面描述的备用流程(这有助于防止入站和出站连接状态不匹配).&lt;br /&gt;
# 如果发起方实体不能从它的SRV查询接收到应答, 它应该(SHOULD)尝试下一节描述的备用流程.&lt;br /&gt;
&lt;br /&gt;
====后备流程====&lt;br /&gt;
&lt;br /&gt;
后备流程应该(SHOULD)是一个常规的 &amp;quot;A&amp;quot; 或 &amp;quot;AAAA&amp;quot; 地址记录解析以决定原始域的IPv4或IPv6地址, 而端口则为 &amp;quot;xmpp-client&amp;quot; 端口(5222)用于客户端-服务器连接或 &amp;quot;xmpp-server&amp;quot; 端口(5269)用于服务器-服务器连接 (这些是在IANA注册的缺省端口，[[RFC6120#端口号和服务名|14.7]] .&lt;br /&gt;
&lt;br /&gt;
如果通过TCP连接不成功, 发起方实体可能尝试找到并使用替代连接方法例如HTTP绑定 (见 [[RFC6120#提示性引用|XEP‑0124]] 和 [[RFC6120#提示性引用|XEP‑0206]] , 它可能使用 [[RFC6120#提示性引用|DNS‑TXT]] 记录(参见 [[RFC6120#提示性引用|XEP‑0156]]) 来搜索.&lt;br /&gt;
&lt;br /&gt;
====什么时候不用SRV====&lt;br /&gt;
&lt;br /&gt;
如果发起方实体已经被显式地配置为一个关联到接收实体的原始域的一个特定的FQDN (以及潜在的端口) (比如,一个特定的原始域 example.net  &amp;quot;写死&amp;quot; 到一个配置好的 apps.example.com 的 FQDN), 鼓励初始方实体使用配置好的名字而不是建议的对原始域的SRV解析流程.&lt;br /&gt;
&lt;br /&gt;
====附加服务使用SRV记录====&lt;br /&gt;
&lt;br /&gt;
很多XMPP服务器以可托管附加服务 (超出本文和 [[RFC6120#常规引用|XMPP-IM]] 定义范围) 这种方式来实现，附加服务的DNS域名典型的形式是主XMPP服务的 &amp;quot;子域名&amp;quot; (例如, conference.example.net 用于 [[RFC6120#常规引用|XEP‑0045]] 服务,相关的XMPP主服务为 example.net ) 或 底层服务的一级域名的 &amp;quot;子域名&amp;quot; (例如, muc.example.com 用于 [[RFC6120#常规引用|XEP‑0045]] 服务，相关的XMPP主服务为 im.example.com ). 如果一个和远程XMPP服务关联的实体希望连接到这样一个附加服务上, 它将生成一个适当的XML节，而远程服务器将尝试通过一个SRV查询资源记录类似 &amp;quot;_xmpp-server._tcp.conference.example.net.&amp;quot; 或 &amp;quot;_xmpp-server._tcp.muc.example.com.&amp;quot; 来解析该附加服务的DNS域名. 所以, 如果一个XMPP服务的管理员希望让远程服务器相关的实体能访问这样的附加服务, 除了用于他们的主XMPP服务的 &amp;quot;_xmpp-server&amp;quot; 记录之外, 他们还需要声明适当的 &amp;quot;_xmpp-server&amp;quot; SRV 记录. 当 SRV 记录不可用的时候, 可使用后备方法 [[RFC6120#后备流程|3.2.2]] 来为附加服务解析域名.&lt;br /&gt;
&lt;br /&gt;
===重连===&lt;br /&gt;
&lt;br /&gt;
XMPP服务器可能在会向连接的客户端和远端服务器提供TCP连接服务的时候意外掉线. 因为这些连接的数量可能非常大, 实体的重连机制寻求解决重连可能导致的对软件性能的冲剂和网络堵塞. 如果实体选择重连, 它: &lt;br /&gt;
&lt;br /&gt;
:* 应该把重连之前等待的秒数设置为0到60之间 (这有助于确保不会所有实体在掉线的同一个时间间隔之后同时尝试重连).&lt;br /&gt;
:* 如果第一次尝试重连没有成功则随后的尝试重连的时间间隔应该越来越长 (例如, 按照 [[RFC6120#提示性引用|ETHERNET]] 描述的 &amp;quot;动态二进制指数后退算法&amp;quot; ).&lt;br /&gt;
&lt;br /&gt;
建议重连的时候使用TLS会话恢复 [[RFC6120#提示性引用|TLS‑RESUME]] . 本文未来的某个版本, 或某个独立的协议, 可能会提供更多详细的关于加速重连过程的方法的指南.&lt;br /&gt;
&lt;br /&gt;
===可靠性===&lt;br /&gt;
&lt;br /&gt;
在XMPP使用常连的TCP连接意味着通过XML流发送的XML节可能不可靠, 因为长连的TCP的各方可能无法及时地了解掉线情况. 在XMPP应用层, 长连接掉线可能导致无法发送节. 尽管本文定义的核心XMPP技术未包括克服这一可靠性缺陷的特性, 有一个XMPP扩展在做这件事 (例如, [[RFC6120#提示性引用|XEP‑0198]] ).&lt;br /&gt;
&lt;br /&gt;
==XML流==&lt;br /&gt;
===流基础===&lt;br /&gt;
&lt;br /&gt;
两个基本概念，使得XMPP实体之间的小的结构化信息有效载荷能快速地进行异步交换：XML流和XML节。这些术语的定义如下。&lt;br /&gt;
&lt;br /&gt;
:XML流的定义:&lt;br /&gt;
::XML流是一个容器，用于任何两个实体通过网络进行XML元素的交换. XML流的开始明确表达为一个打开的 &amp;quot;流头&amp;quot; (即, 一个包含了适当树形和命名空间声明的 XML &amp;lt;stream&amp;gt; 标签), 而这个XML流的结尾明确表达为一个关闭的XML &amp;lt;/stream&amp;gt; 标签. 在流的生存期间, 发起方实体可以通过这个流发送不限数量的XML元素, 这些元素或用来协商这个流 (例如, 完成 [[RFC6120#提示性引用|TLS协商]] 或 [[RFC6120#提示性引用|SASL协商]] ) 或用于 XML节. &amp;quot;发起流&amp;quot; 是从发起方实体 (通常是一个客户端或服务器) 到接收方实体 (通常是一个服务器), 也可视为对应发起方 &amp;quot;连接到&amp;quot; 或 &amp;quot;和......开启会话&amp;quot; 接收方实体. 发起流允许从发起方实体到接收方实体的单向通讯; 为了让接收方实体能够向发起方实体发送节, 接收方实体必须(MUST) 协商一个相反的流 (&amp;quot;应答流&amp;quot;).&lt;br /&gt;
:XML节的定义:&lt;br /&gt;
::XML节是一个XMPP中的基本语义单位. 一个节就是一个第一层元素 (在流的深度=1)，它的元素名是 &amp;quot;message&amp;quot;, &amp;quot;presence&amp;quot;, 或 &amp;quot;iq&amp;quot; ，而它的合格命名空间是 'jabber:client' 或 'jabber:server'. 相比之下, 任何其他命名空间限定的第一层元素都不是一个XML节 (stream errors, stream features, TLS相关的元素, SASL相关的元素, 等等.), 由'jabber:client' 或 'jabber:server' 命名空间限定的 &amp;lt;message/&amp;gt;, &amp;lt;presence/&amp;gt;, 或 &amp;lt;iq/&amp;gt; 元素但不在第一层 (例如, 包含在一个扩展元素中的 &amp;lt;message/&amp;gt; 元素 ( 做报告用的 [[RFC6120#扩展内容|8.4]] )也不是一个XML节, 不是命名空间 'jabber:client' 或 'jabber:server'限定的 &amp;lt;message/&amp;gt;, &amp;lt;presence/&amp;gt;, 或 &amp;lt;iq/&amp;gt; 元素也不是一个XML节. 一个XML节典型的包含一个或多个必要的子元素 (以及相关的属性, 元素, 和 XML 字符串数据) 来传达所需的信息, 子元素可以(MAY)使用任何XML命名空间 (见 [[RFC6120#常规引用|XML‑NAMES]] 和本协议的 [[RFC6120#扩展内容|8.4]]).&lt;br /&gt;
&lt;br /&gt;
有三种节: message, presence, 和 IQ (&amp;quot;Info/Query&amp;quot;的缩写). 这些节类型提供三种不同的通讯原语: 一个 &amp;quot;推送&amp;quot; 机制用于已生成的消息, 一个特定的 &amp;quot;发行-订阅&amp;quot; 机制用于广播网络可用性信息, 和一个 &amp;quot;请求-应答&amp;quot; 机制用于更结构化的数据交换 (类似 [[RFC6120#提示性引用|HTTP]] . 更多解释分别位于 [[RFC6120#Messsage语义|8.2.1]] , [[RFC6120#Presence语义|8.2.2]] , 和 [[RFC6120#IQ语义|8.2.3]] . &lt;br /&gt;
&lt;br /&gt;
考虑一个客户端连接到一个服务器的例子. 客户端通过发送一个流头来发起一个XML流到服务器, 最好在前面加上一个XML声明来指定XML版本和支持的字符串编码 (见 [[RFC6120#包含XML声明|11.5]] 和 [[RFC6120#字符串编码|11.6]] ). 遵循本地策略和服务设置, 该服务器接着以第二个XML流应答回客户端, 最好再次在前面加上一个XML声明. 一旦客户端完成 [[RFC6120#SASL协商|SASL协商]] 和 [[RFC6120#资源绑定|资源绑定]] , 该客户端就能通过这个流来发送不限数量的XML节. 当客户端想要关闭这个流的时候, 它只要简单的发送一个关闭 &amp;lt;/stream&amp;gt; 标签给服务器，如 [[RFC6120#关闭流|4.4]] . &lt;br /&gt;
&lt;br /&gt;
于是, 从本质上讲, 一个XML流作为会话期间发送的XML节的信封, 而另一个XML流作为会话期间接收的XML节的信封. 我们可以用如下的简化模型做一个展示.&amp;lt;br/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
----&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
+--------------------+--------------------+&lt;br /&gt;
| INITIAL STREAM     |  RESPONSE STREAM   |&lt;br /&gt;
+--------------------+--------------------+&lt;br /&gt;
| &amp;lt;stream&amp;gt;           |                    |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
|                    | &amp;lt;stream&amp;gt;           |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
| &amp;lt;presence&amp;gt;         |                    |&lt;br /&gt;
|   &amp;lt;show/&amp;gt;          |                    |&lt;br /&gt;
| &amp;lt;/presence&amp;gt;        |                    |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
| &amp;lt;message to='foo'&amp;gt; |                    |&lt;br /&gt;
|   &amp;lt;body/&amp;gt;          |                    |&lt;br /&gt;
| &amp;lt;/message&amp;gt;         |                    |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
| &amp;lt;iq to='bar'       |                    |&lt;br /&gt;
|     type='get'&amp;gt;    |                    |&lt;br /&gt;
|   &amp;lt;query/&amp;gt;         |                    |&lt;br /&gt;
| &amp;lt;/iq&amp;gt;              |                    |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
|                    | &amp;lt;iq from='bar'     |&lt;br /&gt;
|                    |     type='result'&amp;gt; |&lt;br /&gt;
|                    |   &amp;lt;query/&amp;gt;         |&lt;br /&gt;
|                    | &amp;lt;/iq&amp;gt;              |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
| [ ... ]            |                    |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
|                    | [ ... ]            |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
| &amp;lt;/stream&amp;gt;          |                    |&lt;br /&gt;
|--------------------|--------------------|&lt;br /&gt;
|                    | &amp;lt;/stream&amp;gt;          |&lt;br /&gt;
+--------------------+--------------------+&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt; '''图2: 两路XML流的简化观点''' &amp;lt;/div&amp;gt;&lt;br /&gt;
----&amp;lt;br/&amp;gt;&lt;br /&gt;
那些习惯于以文档为中心的方式看待XML的人可能会发现下面的类比是有益的: &lt;br /&gt;
&lt;br /&gt;
:* 两个XML流像两个 &amp;quot;文档&amp;quot; (相当于 [[RFC6120#常规引用|XML]] 的&amp;quot;文档&amp;quot; 产生)，它们是通过积累XML节来建立的.&lt;br /&gt;
:* 根 &amp;lt;stream/&amp;gt; 元素像每个 &amp;quot;文档&amp;quot; 的 &amp;quot;文档实体&amp;quot; (详见 [[RFC6120#常规引用|XML]] 的4.8章).&lt;br /&gt;
:* 通过流发送的XML节像该 &amp;quot;文档&amp;quot;的 &amp;quot;片段&amp;quot; (详见 [[RFC6120#提示性引用|XML‑FRAG]] ).&lt;br /&gt;
&lt;br /&gt;
无论如何, 这些描述只是类比, 因为XMPP不处理文档和片段而是处理流和节. &lt;br /&gt;
&lt;br /&gt;
本节的其余部分定义XML流（连同相关主题）的以下几个方面：&lt;br /&gt;
&lt;br /&gt;
:* 如何打开流 ( [[RFC6120#打开流|4.2]] )&lt;br /&gt;
:* 流协商过程 ( [[RFC6120#流协商|4.3]] )&lt;br /&gt;
:* 如何关闭流 ( [[RFC6120#关闭流|4.4]] )&lt;br /&gt;
:* XML流的方向性 ( [[RFC6120#方向性|4.5]] )&lt;br /&gt;
:* 如何处理沉默的对端 ( [[RFC6120#处理沉默对端|4.6]] )&lt;br /&gt;
:* 流的XML属性 ( [[RFC6120#流属性|4.7]] )&lt;br /&gt;
:* 流的XML命名空间 ( [[RFC6120#流命名空间|4.8]] )&lt;br /&gt;
:* 和XML流相关的错误处理 ( [[RFC6120#流错误|4.9]] )&lt;br /&gt;
&lt;br /&gt;
===打开流===&lt;br /&gt;
&lt;br /&gt;
连接到接收方实体的适当的IP地址和端口之后, 发起方实体通过发送一个流头 (&amp;quot;发起流头&amp;quot;) 来打开到接收方实体的流. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后接收方实体通过发送一个它自己的流头 (&amp;quot;应答流头&amp;quot;) 来回复发起方实体. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
接着实体们就可以再进行流协商过程的剩余步骤了.&lt;br /&gt;
&lt;br /&gt;
===流协商===&lt;br /&gt;
====基本概念====&lt;br /&gt;
&lt;br /&gt;
因为流的接收方实体可以说是它所服务的域的看门人, 它对客户端或对端服务器的发起的连接有一定的条件要求. 最低程度, 发起方实体在接收方实体被允许发送节之前需要验证接收方实体， (对客户-服务器流来说这意味着使用 [[RFC6120#SASL协商|6]] 中描述的SASL). 无论如何, 接收方实体可以考虑其他验证条件来强制协商, 例如使用 [[RFC6120#TLS协商|5]] 描述的TLS加密. 接收方实体通过交流&amp;quot;stream features&amp;quot;以通知发起方实体这些条件: 发起方需要在接收方接受它发送的XML节之前完成的一系列特别的协议交互, 以及任何自愿协商但是可以提高XML流处理的协议交互 (例如,  [[RFC6120#提示性引用|XEP‑0138]] 描述的建立应用层压缩). &lt;br /&gt;
&lt;br /&gt;
连接条件的存在意味着流需要协商. 层的顺序 (TCP, 然后是TLS, 然后是SASL, 然后是XMPP. 这些顺序如[[RFC6120#层的顺序|13.3]]描述) 意味着流协商是一个多阶段的过程. 进一步的结构由两个因素来施加: (1) 一个给定的流特性可以仅对特定的实体提供，或只在特定的其他特性已经被协商之后提供 (例如, 资源绑定仅在SASL验证之后提供), 和 (2) 流特性可能是强制协商也可能是自愿协商. 最后, 基于安全的原因一个流的参与者们在成功地完成用于特定特性的协议交互之后需要丢弃它们在协商过程中获得的知识 (例如, 在所有情况下的TLS和当可能建立一个安全层的情况下的SASL, 如有关SASL机制的规范所述). 通过刷新旧的流上下文和在现有的TCP连接上交换新的流头就可以做到这一点.&lt;br /&gt;
&lt;br /&gt;
====流特性格式====&lt;br /&gt;
&lt;br /&gt;
如果发起方实体包含在发起流头里的 'version' 属性值设为不低于 &amp;quot;1.0&amp;quot; (见 [[RFC6120#版本|4.7.5]] ), 接收方实体在发送应答流头之后必须发送一个&amp;lt;features/&amp;gt; 子元素 (通常使用 [[RFC6120#命名空间声明和前缀|4.8.5]] 描述的流命名空间前缀作为前缀) 给发起方实体以声明使流协商过程继续下去的任何条件. 每个条件用 &amp;lt;features/&amp;gt; 元素的子元素的格式, 由一个不同于流命名空间和内容命名空间的命名空间来限定. &amp;lt;features/&amp;gt; 元素可以包含一个子元素，多个子元素，或者为空.&lt;br /&gt;
&lt;br /&gt;
:实现备注: 包含在任何给定的&amp;lt;features/&amp;gt;元素内的子元素的顺序不重要.&lt;br /&gt;
&lt;br /&gt;
如果一个特殊的流特性是或者可以是强制协商的, 那个特性的定义需要做以下几件事之一: &lt;br /&gt;
&lt;br /&gt;
:# 声明这个特性总是强制协商的 (例如, XMPP客户端的资源绑定就是这样的); 或&lt;br /&gt;
:# 为接收方实体指定一个方法来标记这个特性在这次交互中为强制协商 (例如, 对于 STARTTLS, 这是通过包含一个空的 &amp;lt;required/&amp;gt; 元素到流特性广告中来实现的, 但这不是对所有流特性的通用格式); 建议用于新的强制协商特性的流特性定义如 STARTTLS 所做的那样通过包含一个空的 &amp;lt;required/&amp;gt; 元素来实现.&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 因为没有通用格式来说明一个特性是强制协商的, 有可能会出现一个发起方实体不能理解的特性而被接收方认为是强制协商的, 而导致流协商过程失败. 尽管这样一个结果是不可取的, 本工作组认为不需要通用格式的情况是很罕见的.&lt;br /&gt;
&lt;br /&gt;
基于安全性的原因, 在某些流特性协商成功之后，发起方有必要发送一个新的发起流头 (例如, 任何情况下的TLS和当建立了安全层的情况下的SASL). 如果一个给定的流特性出现在这种情况下, 那个特性的定义需要指定该特性协商之后的流重启. &lt;br /&gt;
&lt;br /&gt;
一个包含至少一个强制协商特性的&amp;lt;features/&amp;gt;元素表明了流协商没有完成, 发起方实体必须进行进一步的特性协商. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'&amp;gt;&lt;br /&gt;
       &amp;lt;required/&amp;gt;&lt;br /&gt;
     &amp;lt;/starttls&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
一个&amp;lt;features/&amp;gt;元素可以包含不止一个强制协商特性. 这意味着发起方实体能在流协商过程的这个阶段中对强制协商特性进行选择. 举例来说, 可能一个将来的技术将执行和TLS一样的功能, 所以接收方实体可能在这次流协商过程中的同一个阶段声明同时支持TLS和这个将来的技术. 无论如何, 这只适用于流协商过程中的给定阶段而不适用于不同阶段的强制协商特性 (例如, 接收方实体不会声明同时支持STARTTLS和SASL作为强制性协商, 或同时声明SASL和资源绑定为强制协商, 因为TLS需要在SASL之前协商并且SASL需要在资源绑定之前协商). &lt;br /&gt;
&lt;br /&gt;
一个同时包含强制协商和自愿协商特性的&amp;lt;features/&amp;gt;元素表明协商未完成, 发起方实体可以在它尝试协商强制协商特性之前完成自愿协商特性. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/&amp;gt;&lt;br /&gt;
     &amp;lt;compression xmlns='http://jabber.org/features/compress'&amp;gt;&lt;br /&gt;
       &amp;lt;method&amp;gt;zlib&amp;lt;/method&amp;gt;&lt;br /&gt;
       &amp;lt;method&amp;gt;lzw&amp;lt;/method&amp;gt;&lt;br /&gt;
     &amp;lt;/compression&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
一个只包含自愿协商特性的&amp;lt;features/&amp;gt;元素表明流协商已经完成, 发起方实体可以开始发送XML节了. 但是如果发起方实体愿意可以协商更多特性. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;compression xmlns='http://jabber.org/features/compress'&amp;gt;&lt;br /&gt;
       &amp;lt;method&amp;gt;zlib&amp;lt;/method&amp;gt;&lt;br /&gt;
       &amp;lt;method&amp;gt;lzw&amp;lt;/method&amp;gt;&lt;br /&gt;
     &amp;lt;/compression&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
一个空的&amp;lt;features/&amp;gt;元素表明流协商已经完成, 发起方实体可以开始发送XML节了. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:features/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====重启====&lt;br /&gt;
&lt;br /&gt;
在对一个需要流重启的特性成功协商之后, 双方都必须考虑前一个流将被取代, 但是必须不能发送一个关闭的&amp;lt;/stream&amp;gt;标签并且必须不能终止底层的TCP连接; 反之, 双方必须重用现有的连接, 它可以处于一个新的状态(例如, 作为一个TLS协商的结果被加密). 然后发起方实体必须发送一个新的发起流头, 它之前应该放一个如  [[RFC6120#包含XML声明|11.5]] 所述的XML声明. 当接收方实体接收到新的发起流头, 它必须在发送一个新的应答流头(它之前应该放一个如  [[RFC6120#包含XML声明|11.5]] 所述的XML声明）之前生成一个新的流ID(而不是重用旧的流ID).&lt;br /&gt;
&lt;br /&gt;
====重发特性====&lt;br /&gt;
&lt;br /&gt;
接收方实体必须在一个流重启之后发送一个流特性的更新列表给发起方实体. 如果没有更多的特性要被声明，这个更新的流特性列表可以是空的，也可以包含任何特性的组合.&lt;br /&gt;
&lt;br /&gt;
====完成流协商====&lt;br /&gt;
&lt;br /&gt;
接收方实体通过发送一个空的&amp;lt;features/&amp;gt;元素或只包含自愿协商特性的&amp;lt;features/&amp;gt;元素来表明流协商过程的完成. 这样做之后, 接收方实体可以发送一个空的&amp;lt;features/&amp;gt; 元素(例如, 在这些自愿协商特性协商完成之后) 但是必须不能发送额外的流特性给发起方实体(如果接收方实体有新的特性提供, 最好仅限于强制协商或安全关键的特性, 它可以简单地以一个&amp;lt;reset/&amp;gt;流错误( [[RFC6120#reset|4.9.3.16]] )来关闭流并且等发起方重新连接的时候声明新的特性, 最好以一个交错的方法来关闭现有的流，这样不会让所有的发起方同时进行重连). 一旦流协商完成, 发起方就可以一直通过这个流来发送XML节，只要双方都维持着这个流.&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 在下面 [[RFC6120#资源绑定|第7章]] 定义的资源绑定是一个前述规则的一个历史性的例外, 因为对于客户端来说它是强制协商的但使用XML节来达成协商.&lt;br /&gt;
&lt;br /&gt;
在流协商完成之前，发起方实体不能(MUST NOT)尝试发送 [[RFC6120#XML节|XML节]] 给非自身的实体(也就是是说, 客户端的已连接资源或客户端帐号的任何其他已验证的资源) 或给它连接的服务器. 即使发起方尝试这么做, 接收方实体也不能(MUST NOT)接受这些节并且必须以一个&amp;lt;not-authorized/&amp;gt;流错误( [[RFC6120#未授权|4.9.3.12]] )来关闭流. 这个规则只适用于XML节(也就是说, 由内容命名空间限定的 &amp;lt;message/&amp;gt;, &amp;lt;presence/&amp;gt;, 和 &amp;lt;iq/&amp;gt; 元素) 而不是用于流协商的XML元素(例如, 完成 [[RFC6120#STARTTLS协商|TLS协商]] 或 [[RFC6120#SASL协商|SASL协商]] 的元素).&lt;br /&gt;
&lt;br /&gt;
====确定地址====&lt;br /&gt;
&lt;br /&gt;
在一个XML流的双方已经完成了流协商的适当步骤之后, 流的接收方实体必须确定发起方实体的JID. &lt;br /&gt;
&lt;br /&gt;
对于客户端-服务器的通讯, 在服务器能确定客户端的地址之前，[[RFC6120#SASL协商|SASL协商]] 和 [[RFC6120#资源绑定|资源绑定]] 必须完成. 客户端的纯JID (&amp;lt;localpart@domainpart&amp;gt;) 必须是授权身份 (如 [[RFC6120#常规引用|SASL]] 所定义的, 要么 (1) 是 [[RFC6120#SASL协商|SASL协商]] 期间客户端直接与之通讯的身份,要么 (2) 如果SASL协商期间没有指定授权身份，则是从服务器的验证身份指定的. 全JID(&amp;lt;localpart@domainpart/resourcepart&amp;gt;)的资源部分(resourcepart)必须是客户端和服务器在 [[RFC6120#资源绑定|资源绑定]] 期间协商得来的那个资源. 客户端必须不去尝试猜测它的JID而是必须相信在资源绑定期间服务器返回给它的JID. 服务器必须确保返回的这个JID (包含 本地部分(localpart), 域部分(domainpart), 资源部分(resourcepart), 以及分隔符) 遵循定义于 [[RFC6120#常规引用|XMPP‑ADDR]] 的XMPP地址规范格式; 为了满足这个限定, 服务器可以把客户端的发来的JID替换成服务器确定的规范JID并在资源绑定期间使用那个JID来和客户端通讯.&lt;br /&gt;
&lt;br /&gt;
对于服务器-服务器通讯, 发起方服务器的纯JID (&amp;lt;domainpart&amp;gt;) 必须是授权的身份 (定义于 [[RFC6120#常规引用|SASL]] ), 要么 (1) 是[[RFC6120#SASL协商|SASL协商]] 期间发起方服务器直接与之通讯的身份,要么 (2) 如果SASL协商期间没有指定授权身份，则是从接收方服务器的验证身份指定的. 在缺少SASL协商的情况下, 接收方服务器可以认为授权身份是一个和相关确认协议协商的身份(例如, 在 服务器回拨[[RFC6120#常规引用|XEP‑0220]] 中 &amp;lt;result/&amp;gt; 元素的'from'属性.&lt;br /&gt;
&lt;br /&gt;
:安全警告: 因为可能会有第三方在一个安全层例如TLS成功协商之前篡改流上发送的数据, 建议接收服务器谨慎对待这些未得到保护的信息; 这特别适用于由发起方实体发送的第一个发起流头中的'from'和'to'地址.&lt;br /&gt;
&lt;br /&gt;
====流程图====&lt;br /&gt;
&lt;br /&gt;
我们在接下来的非规范性的流程图里为流协商过程总结前述的规则, 以发起方实体的视角来展示. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
                +---------------------+&lt;br /&gt;
                | 打开TCP连接         |&lt;br /&gt;
                +---------------------+&lt;br /&gt;
                           |&lt;br /&gt;
                           v&lt;br /&gt;
                    +---------------+&lt;br /&gt;
                    | 发送发起流头  |&amp;lt;-------------------------+&lt;br /&gt;
                    |               |                          ^&lt;br /&gt;
                    +---------------+                          |&lt;br /&gt;
                           |                                   |&lt;br /&gt;
                           v                                   |&lt;br /&gt;
                   +------------------+                        |&lt;br /&gt;
                   | 接收应答流头     |                        |&lt;br /&gt;
                   |                  |                        |&lt;br /&gt;
                   +------------------+                        |&lt;br /&gt;
                           |                                   |&lt;br /&gt;
                           v                                   |&lt;br /&gt;
                    +----------------+                         |&lt;br /&gt;
                    | 接收流特性     |                         |&lt;br /&gt;
+------------------&amp;gt;|                |                         |&lt;br /&gt;
^   {可选的}        +----------------+                         |&lt;br /&gt;
|                          |                                   |&lt;br /&gt;
|                          v                                   |&lt;br /&gt;
|       +&amp;lt;-----------------+                                   |&lt;br /&gt;
|       |                                                      |&lt;br /&gt;
|    {空?}    ----&amp;gt; {全部自愿?   } ----&amp;gt; {一些强制性?      }   |&lt;br /&gt;
|       |      否          |          否         |             |&lt;br /&gt;
|       | 是               | 是                  | 是          |&lt;br /&gt;
|       |                  v                     v             |&lt;br /&gt;
|       |     +--------------------+    +-----------------+    |&lt;br /&gt;
|       |     | 可以协商或不协商   |    |必须协商一个特性 |    |&lt;br /&gt;
|       |     |       任何一个     |    |                 |    |&lt;br /&gt;
|       |     +--------------------+    +-----------------+    |&lt;br /&gt;
|       v                  |                     |             |&lt;br /&gt;
|   +---------+            v                     |             |&lt;br /&gt;
|   |  完成   |&amp;lt;----- {协商?      }              |             |&lt;br /&gt;
|   +---------+   否       |                     |             |&lt;br /&gt;
|                     是   |                     |             |&lt;br /&gt;
|                          v                     v             |&lt;br /&gt;
|                          +---------&amp;gt;+&amp;lt;---------+             |&lt;br /&gt;
|                                     |                        |&lt;br /&gt;
|                                     v                        |&lt;br /&gt;
+&amp;lt;-------------------------- {强制性重新开始?   } ------------&amp;gt;+&lt;br /&gt;
               否                                        是&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
::::::::'''图表3: 流协商流程图'''&lt;br /&gt;
&lt;br /&gt;
===关闭流===&lt;br /&gt;
&lt;br /&gt;
从一个实体到另一个实体的XML流可以在任何时候关闭, 可以是因为发生了一个特定的流错误 ([[RFC6120#流错误|4.9章]])) 也可以没有任何错误(例如, 当客户端简单地结束它的会话). &lt;br /&gt;
&lt;br /&gt;
通过发送一个关闭的&amp;lt;/stream&amp;gt;标签来关闭流. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
E: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果双方正在使用一个TCP连接上两个流, 或者两个TCP连接上两个流的通信方式, 发送关闭流标签的实体必须按以下步骤进行:&lt;br /&gt;
&lt;br /&gt;
# 在终止底层的TCP连接之前等待另一方也关闭它的出站流; 这让另一方有机会在终止TCP连接之前发完任何到正在关闭的实体的出站数据.&lt;br /&gt;
# 避免通过它的出站流发送任何更多的数据到另一方, 但是继续处理从另一方实体已经接收到的数据(并且, 如果必要, 处理这些数据).&lt;br /&gt;
# 如果另一方没有在一个合理的时间(这里 &amp;quot;合理&amp;quot; 的定义取决于实现或布署)内发送它的关闭流标签则认为两个流都失效了.&lt;br /&gt;
# 从另一方接收到一个反向的关闭流标签之后, 或在等待一段合理的时间之后未收到应答, 终止底层的TCP连接.&lt;br /&gt;
&lt;br /&gt;
:安全警告: 根据 [[RFC6120#常规引用|TLS]] 的7.2.1章节, 为了帮助防止截断攻击，正在关闭流的那一方在终止底层TCP连接之前必须发送一个 TLS close_notify警告, 并且必须从另一方接收到应答的 close_notify警告.&lt;br /&gt;
&lt;br /&gt;
如果双方通过多重TCP连接使用多重流, 那么没有已定义的配对流, 因此其行为取决于实现.&lt;br /&gt;
&lt;br /&gt;
===方向性===&lt;br /&gt;
&lt;br /&gt;
一个XML流总是单向的, 这意味着只能从一个方向通过流来发送XML节(要么从发起方实体到接收方实体，要么从接收方实体到发起方实体). &lt;br /&gt;
&lt;br /&gt;
取决于已协商的会话的类型以及涉及的实体的性质, 该实体可以使用: &lt;br /&gt;
&lt;br /&gt;
:* 在一个TCP连接上跑两个流, 这里第一个流协商的安全性上下文也适用于第二个流. 这对客户端-服务器是典型的情况, 并且服务器必须允许客户端为两个流使用同一个TCP连接.&lt;br /&gt;
:* 在两个TCP连接上跑两个流, 这里每个流是独立保障安全的. 在这种方法下, 一个TCP连接用于发起方实体发送节到接收方实体的那个流, 另一个TCP连接用于接收方实体发送节到发起方实体的那个流. 这对服务器-服务器会话是典型的情况.&lt;br /&gt;
:* 在两个或更多TCP连接上跑多个流, 这里每个流是独立保障安全的. 这个方法有时用于两个大的XMPP服务提供商之间的服务器-服务器通讯; 无论如何, 在 [[RFC6120#按顺序处理|10.1]] 描述的情况下这将导致难于维护从多个流接收到的数据的一致性, 这是为什么如果远程服务器尝试如[[RFC6120#冲突|4.9.3.3]] 所述来协商多个流，本服务器可能以一个&amp;lt;conflict/&amp;gt;流错误([[RFC6120#冲突|4.9.3.3]])来关闭流.&lt;br /&gt;
&lt;br /&gt;
这个方向性的概念只适用于节, 并且明确地不适用于根流(stream root)的第一级子元素, 那些根流是被用来启动或管理流的(例如, 用于TLS协商, SASL协商, 服务器回拨 [[RFC6120#提示性备注|XEP-0220]] , 流管理 [[RFC6120#提示性备注|XEP-0198]] 的第一级元素).&lt;br /&gt;
&lt;br /&gt;
上述的考虑暗示当完成 [[RFC6120#STARTTLS协商|STARTTLS协商]] 和 [RFC6120#SASL协商|SASL协商]] 的时候，两个服务器将使用同一个TCP连接, 但是在流协商过程完成之后，原始的那个TCP连接将仅用于发起方服务器发送XML节到接收方服务器. 为了让接收方服务器能发送XML节给发起方服务器, 接收方服务器将需要反转角色并通过一个单独的TCP连接从接收方服务器向发起方服务器协商一个XML流. 然后这个单独的TCP连接用新一轮的 TLS 和/或 SASL 协商来保证安全性.&lt;br /&gt;
&lt;br /&gt;
:实现备注: 基于历史原因, 一个服务器-服务器会话总是使用两个TCP连接. 这个方法仍然在本文描述的标准行为之内, 类似 [[RFC6120#提示性备注|XEP‑0288]] 的扩展允许服务器们使用单一的TCP连接协商来进行双向的节交换.&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 尽管XMPP开发者们有时对底层TCP连接使用了&amp;quot;单向&amp;quot;和&amp;quot;双向&amp;quot;的概念 (例如, 把用于客户端-服务器会话的TCP连接称为&amp;quot;双向的&amp;quot; 而用于服务器-服务器会话的TCP连接称为&amp;quot;单向的&amp;quot;), 严格来讲一个流总是单向的 (因为发起方实体和接收方实体总是最少有两个流, 每个方向一个) 并且一个TCP连接总是双向的 (因为TCP通讯能从两个方向发送). 方向性应用于TCP连接的应用层通讯, 而不是在TCP连接的传输层通讯本身.&lt;br /&gt;
&lt;br /&gt;
===无响应对端的处理===&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:当连接某个流的实体在一段时间内没有接收到同样连接到该流的另一对等端发来的任何XMPP信息，那么该对等端可能是无响应的。有几个原因很可能引起这种情况发生：&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:#底层的TCP连接死掉。&lt;br /&gt;
:#尽管当底层的TCP连接仍然是激活的时候，XML流被中断了。&lt;br /&gt;
:#对等端是空闲的，只是没有通过其连接的XML流发送XMPP信息到该实体。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:这三个条件最好被分别对待，像下面章节描述的一样。&lt;br /&gt;
&lt;br /&gt;
::实现注意:为了处理无响应的对等端，我们把两个单向的TCP连接当作一个在概念上相当的双向的TCP连接（见4.5节（[[RFC6120#方向性|方向性]]））;然而，实现者要知道在两个单向的TCP连接的情况下，在XMPP应用层对等端对通信的响应将从其第二个TCP连接返回。此外，在每个方向上的多个数据流的使用（大型的XMPP服务提供商间的服务器到服务器之间的连接经常这么部署）使得对XMPP流和底层TCP连接的应用级检查进一步复杂化了，因为任何给定的初始流和任何给定的响应流之间没有必然联系。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====死连接====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:如果底层的TCP连接是死的，流级别的检查（例如：[http://xmpp.org/rfcs/rfc6120.html#XEP-0199 [XEP-0199]]和[http://xmpp.org/rfcs/rfc6120.html#XEP-0198 [XEP-0198]]）是无效的。因此，不管有没有流错误都没必要关闭流，恰当的做法是直接终止TCP连接。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:检查TCP连接的一个通用方法是在XML节之间发送一个空格符（U+0020）,发送空格在XML流中是被允许的，下面[[RFC6120#Whitespace|第11.7节]]中将进行描述。发送这样的一个空格被称作“空格保持激活”（词语“whitespace ping”通常被使用，尽管事实上它不是一个ping,因为“pong”是不可能的）。然而，在TLS认证和SASL认证期间，发送空格符是不允许的，下面[[RFC6120#Data Formatting|第5.3.3节]]和[[RFC6120#Data Formatting|第6.3.5节]]将会描述。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====中断的流====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:即使底层的TCP连接仍然是激活的，对等端很可能从来不对实体发出的XMPP通信请求作出响应，不管是正常的节还是例如在[http://xmpp.org/rfcs/rfc6120.html#XEP-0199 [XEP-0199]]中所定义的应用程序级别ping那样的专门流通信检查，或者在[http://xmpp.org/rfcs/rfc6120.html#XEP-0198 [XEP-0198]]中定义的更全面的流管理协议。在这种情况下，对实体来说恰当的做法是发送&amp;lt;connection-timeout/&amp;gt;流错误（[[RFC6120#connection-timeout|第4.9.3.4节]]）来关闭中断的流。&lt;br /&gt;
&lt;br /&gt;
====空闲对端====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:即使底层的TCP连接仍然激活，并且流没有被中断，对等端很可能在一段时间内都没有发送XML节。在这种情况下，对等端可以（MAY）关闭流（像[[RFC6120#关闭流|第4.4节]]描述的一样），而不是让不再使用的流打开着。如果空闲对等端没有关闭流，那么与该流关联的另一端或者可以（MAY）通过使用第4.4节描述的握手方式来关闭该流，或者发送一个流错误（例如：&amp;lt;resource-constraint/&amp;gt;（[[RFC6120#resource-constraint|第4.9.3.17节]]），如果实体已经到了打开TCP连接数的限制，或者&amp;lt;policy-violation/&amp;gt;（[[RFC6120#policy-violation|第4.9.3.14节]]），如果连接已超出本地超时政策）来关闭该流。然而，层（下面[[RFC6120#Order of Layers|第13.3节]]指定）的顺序要符合，在得出对等端处于空闲状态的结论前，另一端需要去核实底层TCP连接仍然是激活的并且流没有被中断（前面已描述）。此外，在接受空闲对等端时最好宽容一点，因为经验表明，这样做可以提高在XMPP网络上通信的可靠性，并且保持两个服务器之间的流比积极地去超时一个流通常更有效。&lt;br /&gt;
&lt;br /&gt;
====检查方法的使用====&lt;br /&gt;
&lt;br /&gt;
建议实现人员支持任何他们认为合适的流检查和连接检查方法, 但是要小心衡量这些方法对网络的冲击和及时发现中断的流和死TCP连接得到的好处. 使用的任何特定检查方法的时间间隔对本地服务策略都是一个大事情，并且严重依赖于网络环境和给定布署和连接类型的使用场景. 在撰写本文的时候, 建议任何这类检查的执行不要超过每5分钟一次, 并且理想的情况是, 这类检查由客户端发起而不是服务器来发起. 鼓励那些实现XMPP软件和布署XMPP服务的人对适当的流检查和连接检查时间间隔寻求其他的意见, 特别是当使用了功率受限的设备的时候 (例如, 在移动环境).&lt;br /&gt;
&lt;br /&gt;
===流属性===&lt;br /&gt;
根&amp;lt;stream/&amp;gt;元素的属性定义在以下章节. &lt;br /&gt;
&lt;br /&gt;
:安全警告: 在流的保密性和安全性被 [[RFC6120#START协商|第5章]] 描述的TLS或一个相当的安全层(类似SASL GSSAPI机制)保护之前, 一个流头提供的属性们可能会被攻击者篡改.&lt;br /&gt;
&lt;br /&gt;
:实现备注: 根&amp;lt;stream/&amp;gt;元素的属性不是以一个命名空间前缀来前置是因为, 根据 [[RFC6120#常规引用|XML‑NAMES]] 的解释, &amp;quot;[d]缺省的命名空间声明不直接应用用于属性名称; 没有前缀的属性的解释由它们出现的那个节来决定.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====from====&lt;br /&gt;
:'from'属性指定发送流元素的实体的XMPP标识。&lt;br /&gt;
&lt;br /&gt;
对客户机-服务器通信的发起流头而言，'from'属性是控制客户端的主要XMPP标识，如格式为&amp;lt;localpart@domainpart&amp;gt;的JID。客户端可能不知道XMPP标识，因为XMPP标识不是在XMPP应用层的等级上被分配的（如通用安全服务应用程序接口[http://xmpp.org/rfcs/rfc6120.html#GSS-API [GSS-API]]中描述），或者从客户端提供的信息由服务器生成（像采用SASL EXTERNAL机制的终端用户证书部署）。此外，如果客户端认为XMPP标识是私人信息，那么在流的保密性和完整性被TLS或等效的安全层保护之前是不提倡包括一个'from'属性的。但是，如果客户端知道XMPP标识，它应该（SHOULD）在流的保密性和完整性被TLS或等效的安全层保护之后包括'from'属性。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:对于服务器-服务器通信的发起流头而言，'from'属性是服务器配置的FQDN之一，如，格式如&amp;lt;domainpart&amp;gt;的JID。初始服务器可能有一个以上的XMPP标识，如，在服务器提供虚拟主机的情况下，所以它需要选择一个与此输出流关联的标识（如：基于触发流协商尝试的节的'to'属性）。因为服务器是XMPP网络上的“公共实体”，它必须（MUST）在流的保密性和完整性被TLS或等效的安全层保护之后包含'from'属性。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='example.net'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:server'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:对于客户端-服务器和服务器-服务器通信的响应流头，接收实体必须（MUST）包括'from'属性并且必须（MUST）把该属性值设置为接收实体的FQDN之一（可以（MAY）是一个正式域名（FQDN），而不是发起流头中'to'属性指定的值，下面[[RFC6120#当主机未定义或未知时会发生流错误|第4.9.1.3节]]和[[RFC6120#host-unknown|第4.9.3.6节]]将描述）。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
无论'from'属性是否被包括，在和其它实体交换XML节之前，每个实体必须（MUST）核实其它实体的身份，下面[[RFC6120#Peer Entity Authentication|第13.5节]]将描述。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:互操作性备注：基于[http://xmpp.org/rfcs/rfc6120.html#RFC3920 [RFC3920]]的实现在任何流头（即使其保密性和完整性受到保护）中不包括'from'地址是可以的，一个实体在接收这样的流头时应该（SHOULD）宽容些。&lt;br /&gt;
&lt;br /&gt;
====to====&lt;br /&gt;
:对于客户端-服务器和服务器-服务器通信中的发起流头，发起实体必须（MUST）包含'to'属性，并且必须（MUST）使用发起实体知道或者期望接收实体提供服务的域名来设置'to'属性的值。（在其他方面，如[http://xmpp.org/rfcs/rfc6120.html#TLS-EXT [TLS-EXT]]中所描述，在TLS协商期间的服务器名称显示，也可以提供类似的信息。）&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:对于客户端-服务器通信的响应流头，如果客户端在其发起流头中包含'from'属性，那么服务器在应答流头中必须（MUST）包含'to'属性，并且必须（MUST）使用初始化流头中'from'属性指定的裸JID来设置'to'属性的值。如果客户端在其初始化流头中不包含'from'属性，那么服务器在应答流中不必（MUST NOT）包含'to'属性。&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
:对于服务器-服务器通信的响应流头，接收实体在应答流头中必须（MUST）包含'to'属性，并且必须（MUST）使用发起流头中'from'属性指定的域名部分来设置'to'属性的值。&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='g4qSvGvBxJ+xeAd7QKezOQJFFlw='&lt;br /&gt;
       to='example.net'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:server'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:无论是否包含'to'属性，每个实体在与其它实体交换XML节之前必须（MUST）先核实其它实体的身份，如下面[[RFC#Peer Entity Authentication|第13.5节]]所描述。&lt;br /&gt;
&lt;br /&gt;
::互操作性备注：基于[http://xmpp.org/rfcs/rfc6120.html#RFC3920 [RFC3920]]的实现在任何流头中不包括'to'地址是可以的，一个实体在接收这样的流头时应该（SHOULD）宽容些。&lt;br /&gt;
&lt;br /&gt;
====id====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:'id'属性是流的唯一标识符，称为“流ID”。流ID必须（MUST）由接收实体在发送应答流头时生成，并且在接收的应用（一般是一个服务器）内部，所生成的流ID必须（MUST）是唯一的。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
::'''安全警告：'''流ID都必须（MUST）是不可预测的和非重复的，因为身份验证机制重用它时可能引起安全隐患，如服务器回拨[http://xmpp.org/rfcs/rfc6120.html#XEP-0220 [XEP-0220]]和“XMPP 0.9”身份验证机制，“XMPP 0.9”机制是RFC 3920在XMPP使用SASL机制之前所使用的身份认证机制;出于安全目的 的随机性建议,见[http://xmpp.org/rfcs/rfc6120.html#RANDOM [RANDOM]]。&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
:对于初始流头，初始实体不必（MUST NOT）包含'id'属性;但是，如果包含'id'属性，接收实体必须（MUST）忽略它。&lt;br /&gt;
&lt;br /&gt;
:对于响应流头，接收实体必须（MUST）包括'id'属性。&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
::'''互用性备注：'''在RFC 3920中，列入'id'属性的文字含糊不清的，导致一些实现的id属性脱离了响应流头。&lt;br /&gt;
&lt;br /&gt;
====xml:lang====&lt;br /&gt;
&lt;br /&gt;
'xml:lang'属性指定一个实体在该流上发送的任何可读XML字符串数据的首选或缺省语言(XML节也可以拥有'xml:lang'属性, 定义在 [[RFC6120#xml:lang|8.1.5]] ). 这个属性的语法定义于 [[RFC6120#常规引用|XML]] 的2.12节; 特别是, 'xml:lang'属性必须符合 NMTOKEN 数据类型 (定义于 [[RFC6120#常规引用|XML]] 的2.3节) 同时必须符合定义于 [[RFC6120#常规引用|LANGTAGS]] 的语言标识符.&lt;br /&gt;
&lt;br /&gt;
对于发起流头, 发起方实体应该包含 'xml:lang' 属性. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=xml&amp;gt;&lt;br /&gt;
I: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
对于应答流头, 接收方实体必须包含 'xml:lang' 属性. 应用以下规则:&lt;br /&gt;
&lt;br /&gt;
:* 如果发起方实体在它的发起流头包含了'xml:lang'属性，而接收方实体在它生成和发送给发起方实体的可读XML字符串数据(例如, 流和节错误中的&amp;lt;text/&amp;gt;元素)中支持那个语言, 'xml:lang'属性值必须是发起方实体首选语言的标识符(例如, &amp;quot;de-CH&amp;quot;).&lt;br /&gt;
:* 如果接收方实体根据定义于[[RFC6120#常规引用|LANGMATCH]] 3.4节的 &amp;quot;lookup scheme&amp;quot;(例如, &amp;quot;de&amp;quot; 而不是 &amp;quot;de-CH&amp;quot;)支持一种和发起方实体首选语言匹配的语言, 那么'xml:lang'属性值应该是匹配语言的标识符.&lt;br /&gt;
:* 如果接收方实体不支持发起方实体的首选语言或根据查找方案匹配的语言(或者如果发起方实体未在其发起流头中包含'xml:lang'属性), 那么'xml:lang'属性值必须是接收方实体的缺省语言的标识符(例如, &amp;quot;en&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=xml&amp;gt;&lt;br /&gt;
R: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果发起方实体在它的发起流头包含了'xml:lang'属性, 接收方实体应该记住那个值并以此作为发起方实体通过当前流发送的所有节的缺省 xml:lang . 如下面的 [[RFC6120#xml:lang|8.1.5]] 所述, 发起方实体可以在它通过这个流发送的任何XML节中包含'xml:lang'属性. 如果发起方实体在任何这类节中未包含'xml:lang'属性, 接收方实体在路由它到远程服务器或递送它到一个已连接的客户端时应该加上'xml:lang'属性, 而这个属性的值必须是发起方实体的首选语言的标识符(即使接收方实体生成和发送给发起方实体的可读XML字符串数据不支持该语言, 类似流或节错误等). 如果发起方实体在任何这类节中包含了'xml:lang'属性, 接收方实体在路由它到远程服务器或递送到已连接的客户端时必须不能修改和删除它.&lt;br /&gt;
&lt;br /&gt;
====version====&lt;br /&gt;
:包含值至少为“1.0”的版本属性传达了对本文所定义的流相关的协议支持的信号，这些流相关的协议包括[[RFC6120#STARTTLS Negotiation|TLS协商]]，[[RFC6120#SASL Negotiation|SASL协商]]，[[RFC6120#流特性格式|流特征]]，[[RFC6120#流错误|流错误]]。&lt;br /&gt;
&lt;br /&gt;
:本文规定的XMPP版本是“1.0”；尤其，XMPP 1.0 封装了流相关协议以及三个定义的XML节类型的基本语义（&amp;lt;message/&amp;gt;, &amp;lt;presence/&amp;gt;,和 &amp;lt;iq/&amp;gt;，下面[[RFC6120#Message Semantics|8.2.1节]]，[[RFC6120#Message Semantics|8.2.2节]]，[[RFC6120#Message Semantics|8.2.3节]]分别描述）。&lt;br /&gt;
&lt;br /&gt;
:XMPP版本编号方案是“&amp;lt;主版本&amp;gt;.&amp;lt;次版本&amp;gt;（‘&amp;lt;major&amp;gt;.&amp;lt;minor&amp;gt;’）”。主版本和次版本号必须（MUST）视为独立的整数，并且每个数可能（MAY）会以高于一个单一的数字的方式递增。因此，“XMPP 2.4”版本将低于“XMPP 2.13”，同理，“XMPP 2.13”版本将低于“XMPP 12.3”。接受方必须（MUST）忽略前导零（例如，“XMPP 6.01”），并且不能（MUST NOT）发送。&lt;br /&gt;
&lt;br /&gt;
:只有重大的新功能已被添加到核心协议（如：对message, presence, 或者IQ节新定义一个‘TYPE’属性值），次要版本号才递增。具有较小次版本号的实体必须（MUST）忽略版本比它大的次版本号，但是具有较大次版本号的实体为了一些信息目的可以使用版本比它小的次版本号（如：具有较大次版本号的实体将仅仅关注其通信器将不能理解‘TYPE’属性的值，因此不发送它）。&lt;br /&gt;
&lt;br /&gt;
:下述规则适用于流头内“version”属性的生成和处理：&lt;br /&gt;
:#初始化实体必须（MUST）在初始化流头中设置‘version’属性的值为它所支持的最高版本号（如：如果它支持的最高版本号是本文中定义的，它必须（MUST）设置该值为“1.0”）。&lt;br /&gt;
:#接收实体必须（MUST）在应答流头中设置‘version’属性的值或者为初始化实体提供的值，或者为接收实体所支持的最高版本号，以较低者为准。接收实体必须（MUST）执行主要和次要版本号的数值比较，而不是关于“&amp;lt;主版本&amp;gt;.&amp;lt;次版本&amp;gt;（‘&amp;lt;major&amp;gt;.&amp;lt;minor&amp;gt;’）”的字符串匹配。&lt;br /&gt;
:#如果在应答流头中包含的版本号至少在主版本号上比在初始化流头中包含的版本号低，那么较新版本的实体不能与旧版本的实体互操作，初始化实体应该（SHOULD）通过发送一个包含&amp;lt;unsupported-version/&amp;gt;元素的流错误（[[RFC6120#unsupported-version|第4.9.3.25节]]）来关闭流。&lt;br /&gt;
:#如果任何一个实体接收到一个没有‘version’属性的流头，该实体必须（MUST）认为其他实体支持的版本是“0.9”，并且不应该在响应流头中包含‘version’属性。&lt;br /&gt;
&lt;br /&gt;
====流属性总结====&lt;br /&gt;
:下表总结了根元素&amp;lt;stream/&amp;gt;的属性。&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
+----------+--------------------------+-------------------------+&lt;br /&gt;
|          |    初始实体 到 接收实体     |    接收实体 到 初始实体    |&lt;br /&gt;
+----------+--------------------------+-------------------------+&lt;br /&gt;
| to       | 接收实体JID               | 初始实体JID              |&lt;br /&gt;
| from     | 初始实体JID               | 接收实体JID              |&lt;br /&gt;
| id       | 忽  略                       | 流标识                     |&lt;br /&gt;
| xml:lang | 默认语言                     | 默认语言                   |&lt;br /&gt;
| version  | XMPP 1.0+ supported      | XMPP 1.0+ supported     |&lt;br /&gt;
+----------+--------------------------+-------------------------+&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''图4：流属性'''&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===XML命名空间===&lt;br /&gt;
读者可以参考 [[RFC6120#常规引用|XML‑NAMES]] 来完整地理解本章的概念, 特别是本协议的第三章和第6.2节的 &amp;quot;缺省命名空间&amp;quot; 的概念. &lt;br /&gt;
&lt;br /&gt;
====流命名空间====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;stream/&amp;gt; 根元素 (&amp;quot;流头&amp;quot;) 必须由 'http://etherx.jabber.org/streams' (即 &amp;quot;流命名空间&amp;quot;) 命名空间来限定. 如果违反了这个规则, 接受到该流头的实体必须以一个流错误来关闭流, 这个流错误应该是 &amp;lt;invalid-namespace/&amp;gt; ([[RFC6120#invalid-namespace|4.9.3.10]]), 尽管一些现存的实现发送的是 &amp;lt;bad-format/&amp;gt; ([[RFC6120#bad-forma|4.9.3.1]]) .&lt;br /&gt;
&lt;br /&gt;
====内容命名空间====&lt;br /&gt;
&lt;br /&gt;
实体可以声明一个&amp;quot;内容命名空间&amp;quot; 作为缺省的命名空间用于在流上发送的数据 (也就是那些不属于由流命名空间限定的元素的数据). 如果这样做, (1) 内容命名空间必须不同于流命名空间, 并且 (2) 内容命名空间对于发起流和应答流必须是相同的，使得两个流的限定是一致的. 内容命名空间应用所有从流上发送的一级子元素,出非被显式地由另一个命名空间来限定 (即, 内容命名空间是缺省命名空间).&lt;br /&gt;
&lt;br /&gt;
另外 (也就是说, 不定义内容命名空间作为缺省命名空间), 实体可以显式地为流的每个一级子元素限定命名空间, 使用所谓 &amp;quot;自由前缀规范&amp;quot;. 这两种方式在下面的例子中展示.&lt;br /&gt;
&lt;br /&gt;
当声明了一个内容命名空间作为缺省命名空间时, 大致来说一个流看卡里类似下面的例子. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;stream:stream&lt;br /&gt;
    from='juliet@im.example.com'&lt;br /&gt;
    to='im.example.com'&lt;br /&gt;
    version='1.0'&lt;br /&gt;
    xml:lang='en'&lt;br /&gt;
    xmlns='jabber:client'&lt;br /&gt;
    xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
  &amp;lt;message&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;foo&amp;lt;/body&amp;gt;&lt;br /&gt;
  &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当没有定义内容命名空间作为缺省命名空间而使用所谓&amp;quot;自由前缀规范&amp;quot;时, 大致一个流看起来像以下例子. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;stream&lt;br /&gt;
    from='juliet@im.example.com'&lt;br /&gt;
    to='im.example.com'&lt;br /&gt;
    version='1.0'&lt;br /&gt;
    xml:lang='en'&lt;br /&gt;
    xmlns='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
  &amp;lt;message xmlns='jabber:client'&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;foo&amp;lt;/body&amp;gt;&lt;br /&gt;
  &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
传统上, 大多数XMPP实现在流头使用了 把内容命名空间作为缺省命名空间 的方式，而不是 自由前缀规范 的方式; 无论如何, 两种方式都是可以接受的，因为它们在语义上是等价的.&lt;br /&gt;
&lt;br /&gt;
====XMPP内容命名空间====&lt;br /&gt;
&lt;br /&gt;
本协议定义的XMPP使用两种内容命名空间: 'jabber:client' 和 'jabber:server'. 这些命名空间差不多相同但是用于不同的上下文 ('jabber:client'用于 客户端-服务器 通讯而'jabber:server' 用于 服务器-服务器 通讯). 两者之间唯一的不同是在通过'jabber:client'命名空间限定的XML流发送的节中 'to' 和 'from' 属性是可选的, 而在'jabber:server'限定的XML流发送的节中它们是必需的. 支持这些内容命名空间意味着支持常规属性和所有三个核心节类型 (message, presence, 和IQ)的基本语义. &lt;br /&gt;
&lt;br /&gt;
一个实现可以支持不同于 'jabber:client' 或 'jabber:server' 的内容命名空间. 然而, 因为这些命名空间将定义不同于XMPP的应用, 它们将在单独的协议中定义. &lt;br /&gt;
&lt;br /&gt;
一个实现可以拒绝支持任何与缺省命名空间不同的其他内容命名空间. 如果一个实体不支持它接收到的一个一级子元素的内容命名空间, 它必须以 &amp;lt;invalid-namespace/&amp;gt; 流错误([[RFC6120#invalid-namespace|4.9.3.10]])关闭这个流 .&lt;br /&gt;
&lt;br /&gt;
客户端实现必须支持'jabber:client'内容命名空间作为缺省命名空间. 'jabber:server'内容命名空间超出了XMPP客户端的范畴, 并且客户端不能(MUST NOT)发送'jabber:server'命名空间限定的节. &lt;br /&gt;
&lt;br /&gt;
服务器实现必须同时支持'jabber:client'命名空间(当这个流用于客户端和服务器之间通讯的时候)和'jabber:server'命名空间(当这个流用于两个服务器之间的通讯的时候)作为缺省命名空间. 和一个已连接的客户端通讯时,该服务器不能(MUST NOT)发送由'jabber:server'命名空间限定的节; 和一个对端服务器通讯时, 该服务器不能(MUST NOT)发送由'jabber:client'命名空间限定的节. &lt;br /&gt;
&lt;br /&gt;
:实现备注: 因为一个客户端通过一个内容命名空间为'jabber:client'的流发送节, 如果一个服务器路由一个它从一个已连接的客户端收到的节到另一个对端服务器,那么它需要为这个节 &amp;quot;重新界定范围(re-scope)&amp;quot; ，所以它的命名空间是'jabber:server'. 类似的, 如果一个服务器递送一个它从别的对端服务器收到的节到一个已连接的客户端，那么它需要给这个节 &amp;quot;重新界定范围&amp;quot; ，所以它的内容命名空间是'jabber:client'. 这个规则适用于[[RFC6120#流基础|4.1]]定义的XML节(即, 一个由'jabber:client'或'jabber:server'命名空间限定的顶级的 &amp;lt;message/&amp;gt;, &amp;lt;presence/&amp;gt;, 或 &amp;lt;iq/&amp;gt; 元素 ), 并且命名空间继承到一个节的所有子元素. 然而, 这个规则不适用于非'jabber:client'和'jabber:server'限定的元素以及它们的任何子元素(例如, 一个包含了用于报告的扩展元素([[RFC6120#扩展内容|8.1]])的 &amp;lt;message/&amp;gt;元素). 尽管不可能禁止一个实体在一个扩展元素中生成的节的子元素由'jabber:client'或'jabber:server'命名空间来限定, 现有的实现处理这类节的方法是不一致的; 因此, 建议实现者自己权衡选择降低互操作性还是损失这些节的功能. 最后, 建议服务器对于使用其他流连接方法和替代的XMPP连接方法而来的节重新界定范围, 例如那些定义在 [[XEP-0124]] , [[RFC6120#提示性备注|XEP-0206]] , [[XEP-0114]] , 和 [[RFC6120#提示性备注|XEP-0225]] 中的节.&lt;br /&gt;
&lt;br /&gt;
====其他命名空间====&lt;br /&gt;
&lt;br /&gt;
参与一个流的双方都可以发送非内容命名空间和流命名空间限定的数据. 例如, 和TLS协商以及SASL协商相关的数据如何交换, 以及类似 流管理[[RFC6120#提示性备注|XEP‑0198]]和服务器回拨[[RFC6120#提示性备注|XEP‑0220]]的XMPP扩展.&lt;br /&gt;
&lt;br /&gt;
:互操作性备注: 由于历史的原因, 一些服务器实现预期有一个'jabber:server:dialback'命名空间的声明用于 服务器-服务器 流, 详见[[RFC6120#提示性备注|XEP‑0220]].&lt;br /&gt;
&lt;br /&gt;
无论如何, 一个XMPP服务器不能(MUST NOT)路由或递送这样一个从入站流中接收到的数据，如果那个数据 (a) 是由其他命名空间限定 并且 (b) 地址指向的实体不是一个服务器, 除非从出站流发送数据出来的另一方服务器显式地协商或声明支持从该服务器接收任意数据. 制定这个规则是因为XMPP是设计用来做XML节交换的(而不是任意XML数据), 也因为允许实体发送任意数据到其他实体可能会导致恶意数据交换显著增加. 作为本规则的例子, example.net 域主机将不会从 &amp;lt;romeo@example.net&amp;gt; 到 &amp;lt;juliet@example.com&amp;gt; 的路由一级XML元素: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;ns1:foo xmlns:ns1='http://example.org/ns1'&lt;br /&gt;
           from='romeo@example.net/resource1'&lt;br /&gt;
           to='juliet@example.com'&amp;gt;&lt;br /&gt;
    &amp;lt;ns1:bar/&amp;gt;&lt;br /&gt;
  &amp;lt;/ns1:foo&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这个规则也适用于看起来像节但是命名空间不正确所以并不是真的节的一级元素(参见 [[RFC6120#命名空间声明和前缀|4.8.5]]), 例如: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;ns2:message xmlns:ns2='http://example.org/ns2'&lt;br /&gt;
               from='romeo@example.net/resource1'&lt;br /&gt;
               to='juliet@example.com'&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;hi&amp;lt;/body&amp;gt;&lt;br /&gt;
  &amp;lt;/ns2:message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在从一个入站流中接收到任意一级XML元素之后, 服务器必须要么忽略该数据要么以一个流错误关闭这个流, 这个流错误应该是 &amp;lt;unsupported-stanza-type/&amp;gt; ([[RFC6120#不支持的流类型|4.9.3.24]]).&lt;br /&gt;
&lt;br /&gt;
====命名空间声明和前缀====&lt;br /&gt;
&lt;br /&gt;
因为内容命名空间不同于流命名空间, 如果把一个内容命名空间声明为缺省命名空间，那么以下论断为真: &lt;br /&gt;
&lt;br /&gt;
:#流头需要包含一个同时用于内容命名空间和流命名空间的命名空间声明.&lt;br /&gt;
:#流命名空间的声明需要包含用于流命名空间的前缀.&lt;br /&gt;
&lt;br /&gt;
:互操作性备注: 由于历史原因, 一个实现可能只包含前缀'stream'用于流命名空间(包含了前缀的结果就像&amp;lt;stream:stream&amp;gt;和&amp;lt;stream:features&amp;gt;); 这个来自[[RFC3920]]的规范保留下来用于向后兼容. 实现如果使用不同于'stream'的前缀用于流命名空间将导致互操作性问题. 如果实体接收到一个流头而该流头的流命名空间前缀是不可接受的, 它必须以一个流错误来关闭这个流, 这个流错误应该是 &amp;lt;bad-namespace-prefix/&amp;gt; ([[RFC6120#bad-namespace-prefix|4.9.3.2]]), 虽然一些现有的实现发送的是 &amp;lt;bad-format/&amp;gt; ([[RFC6120#bad-format|4.9.3.1]]) .&lt;br /&gt;
&lt;br /&gt;
一个实现不能(MUST NOT)为由内容命名空间限定的元素生成命名空间前缀(即, 在流上发送的数据的缺省命名空间)，如果内容命名空间是'jabber:client'或'jabber:server'. 例如, 以下是非法的: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;stream:stream&lt;br /&gt;
    from='juliet@im.example.com'&lt;br /&gt;
    to='im.example.com'&lt;br /&gt;
    version='1.0'&lt;br /&gt;
    xml:lang='en'&lt;br /&gt;
    xmlns='jabber:client'&lt;br /&gt;
    xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;foo:message xmlns:foo='jabber:client'&amp;gt;&lt;br /&gt;
    &amp;lt;foo:body&amp;gt;foo&amp;lt;/foo:body&amp;gt;&lt;br /&gt;
  &amp;lt;/foo:message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
XMPP实体不应该接受违反这一规则的数据(特别是, XMPP服务器如果不首先纠正这个错误，就不能(MUST NOT）路由这类数据到另一个实体); 替代方案是，它应该要么忽略这个数据要么以流错误来关闭这个流, 这个流错误应该是 &amp;lt;bad-namespace-prefix/&amp;gt; ([[RFC6120#bad-namespace-prefix|4.9.3.2]]). &lt;br /&gt;
&lt;br /&gt;
在一个流头中对命名空间的声明必须只应用于那个流(例如, 'jabber:server:dialback' 命名空间用于服务器回拨 [[XEP‑0220]] ). 特别是, 因为用于通过流路由或递送到其他实体的XML节将丢失在那些生成节的原始流头中的命名空间的上下文, 这些节中的扩展内容的命名空间不能(MUST NOT)在那个流头中声明(参见 [[RFC6120#扩展内容|8.4]]). 如果流的参与双方声明了这样的命名空间, 这个流的其他参与方应该以&amp;lt;invalid-namespace/&amp;gt;流错误关闭该流([[RFC6120#invalid-namespace|4.9.3.10]]). 在任何情况下, 实体必须确保当从入站流路由或递送节到出战流的时候，这些命名空间(根据本章)被正确地声明 .&lt;br /&gt;
&lt;br /&gt;
===流错误===&lt;br /&gt;
&lt;br /&gt;
流的根元素可以包含一个由流命名空间限定的&amp;lt;error/&amp;gt;子元素. 这个错误子元素将由兼容的实体来发送，如果它发现发生了一个流错误. &lt;br /&gt;
&lt;br /&gt;
====规则====&lt;br /&gt;
&lt;br /&gt;
以下规则适用于流这一级的错误. &lt;br /&gt;
&lt;br /&gt;
=====流错误是不可恢复的=====&lt;br /&gt;
&lt;br /&gt;
流级别的错误是不可恢复的. 所以, 如果一个错误发生在流这个级别, 检测到这个错误的实体必须发送一个&amp;lt;error/&amp;gt;元素，其中包含适当的子元素以指明错误情况，并如[[RFC6120#关闭流|4.4]]所述立刻关闭这个流.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&amp;gt;&amp;lt;body&amp;gt;No closing tag!&amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;not-well-formed&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
接着收到这个流错误的实体将如[[RFC6120#关闭流|4.4]]所述关闭这个流. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====流错误可能发生在安装过程中=====&lt;br /&gt;
&lt;br /&gt;
如果该错误是被初始化流头触发的, 那么接收方实体必须仍然发送打开的&amp;lt;stream&amp;gt;标签, 把这个&amp;lt;error/&amp;gt;元素作为该流元素的子元素, 并且发送关闭流的&amp;lt;/stream&amp;gt;标签(最好在同一个TCP包里). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://wrong.namespace.example.org/'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;invalid-namespace&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====当主机未定义或未知时会发生流错误=====&lt;br /&gt;
&lt;br /&gt;
如果初始化实体未提供'to'属性或在'to'属性里提供了一个未知的主机并且这个错误发生在流安装的时候, 在接收方实体关闭这个流之前，由接收方实体返回给初始方实体的流头的'from'属性必须要么是接收方实体的可靠的完整域名要么是空字符串. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='unknown.host.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;host-unknown&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====流错误发到哪=====&lt;br /&gt;
&lt;br /&gt;
当在初始方实体和接收方实体之间使用了两个TCP连接(每个方向使用一个连接)而不是使用单独的双向连接时, 适用以下规则: &lt;br /&gt;
&lt;br /&gt;
:* 和初始方流相关的流级别错误由接收方实体在应答流中通过同一个TCP连接返回.&lt;br /&gt;
:* 从初始方实体用同一个TCP连接通过初始流发送的出站节所触发的节错误(区别于流级别的错误)，接收方实体应通过另一个(&amp;quot;返回&amp;quot;)TCP连接的应答流中返回，因为从初始方实体的角度来看这个(返回错误的)节是入站节.&lt;br /&gt;
&lt;br /&gt;
====语法====&lt;br /&gt;
&lt;br /&gt;
流错误的语法如下所示, 显示在中括号 '[' 和 ']' 的XML数据是可选的. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;stream:error&amp;gt;&lt;br /&gt;
  &amp;lt;defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
  [&amp;lt;text xmlns='urn:ietf:params:xml:ns:xmpp-streams'&lt;br /&gt;
         xml:lang='langcode'&amp;gt;&lt;br /&gt;
     OPTIONAL descriptive text&lt;br /&gt;
  &amp;lt;/text&amp;gt;]&lt;br /&gt;
  [OPTIONAL application-specific condition element]&lt;br /&gt;
&amp;lt;/stream:error&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;defined-condition&amp;quot; 必须对应 [[RFC6120#已定义的错误条件|4.9.3]] 中定义的流错误条件之一. 然而, 因为将来肯能定义额外的错误条件, 如果实体接收到一个它不理解的流错误条件，那么它必须把未知的条件当作 &amp;lt;undefined-condition/&amp;gt; ([[RFC6120#undefined-condition|4.9.3.21]]). 如果一个XMPP扩展的设计者或XMPP实现的开发者需要使用未在本协议中定义的流错误条件来通讯, 他们可以定义一个由应用层命名空间限定的应用特有的错误条件元素来达到这个目的. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;error/&amp;gt;元素:&lt;br /&gt;
&lt;br /&gt;
:* 必须包含一个对应已定义错误条件之一的子元素; 这个元素必须由 'urn:ietf:params:xml:ns:xmpp-streams' 命名空间限定.&lt;br /&gt;
:* 可以包含一个内有XML字符串数据的 &amp;lt;text/&amp;gt; 子元素用来描述错误细节; 这个元素必须由 'urn:ietf:params:xml:ns:xmpp-streams' 命名空间限定并且应该拥有一个 'xml:lang' 属性来指定XML字符串数据的自然语言.&lt;br /&gt;
:* 可以包含一个子元素用于应用特有的错误条件; 这个元素必须由一个应用定义的命名空间来限定，并且它的结构也由该命名空间来定义 (见 [[RFC6120#应用特有的条件|4.9.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;text/&amp;gt; 元素是可选的. 如果有它, 它必须只用于提供描述性或诊断性的信息，用来补充一个已定义的条件或应用特有的条件的含义. 它不能(MUST NOT)被应用程序解释执行. 它不能(MUST NOT)被用作向自然人用户展示的错误消息, 但是可以被用作和已定义条件元素(以及, 可选地, 应用特有的条件元素)相关的错误消息的额外信息.&lt;br /&gt;
&lt;br /&gt;
====已定义的流错误条件====&lt;br /&gt;
&lt;br /&gt;
以下是已定义的流级别的错误条件. &lt;br /&gt;
&lt;br /&gt;
=====bad-format=====&lt;br /&gt;
&lt;br /&gt;
实体发送了无法处理的XML.&lt;br /&gt;
&lt;br /&gt;
(在以下例子中, 客户端发送了一个非XML的XMPP消息, 它也可能会触发一个 &amp;lt;not-well-formed/&amp;gt; 流错误( [[RFC6120#not-well-formed|4.9.3.13]]).) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;No closing tag!&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;bad-format&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:这个错误可以用更多特定的XML相关的错误来替代, 例如 &amp;lt;bad-namespace-prefix/&amp;gt;, &amp;lt;invalid-xml/&amp;gt;, &amp;lt;not-well-formed/&amp;gt;, &amp;lt;restricted-xml/&amp;gt;, 和 &amp;lt;unsupported-encoding/&amp;gt;. 无论如何, 建议使用更多特定的错误.&lt;br /&gt;
&lt;br /&gt;
=====bad-namespace-prefix=====&lt;br /&gt;
&lt;br /&gt;
实体发送了不被支持的命名空间前缀, 或在一个需要这样的前缀的元素中没有发送命名空间前缀 (见 [[RFC6120#XML命名空间名字和前缀|11.2]]).&lt;br /&gt;
&lt;br /&gt;
(在以下例子中, 客户端指定了一个命名空间前缀 &amp;quot;foobar&amp;quot; 用于XML流命名空间.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;foobar:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:foobar='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;bad-namespace-prefix&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====conflict=====&lt;br /&gt;
&lt;br /&gt;
服务器要么 (1) 关闭这个实体现存的流(如果和现有流冲突的新流已经被初始化了), 要么 (2) 拒绝这个实体的新流(如果允许这个新的流将导致和现有的流冲突(例如, 服务器限制来自同一IP地址的连接数量或对于给定的域对只允许一个 服务器-服务器 流，以确保[[RFC6120#顺序处理|10.1]]所述的顺序处理)).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;conflict&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果客户端收到一个&amp;lt;conflict/&amp;gt;流错误( [[RFC6120#conflict|4.9.3.3]]), 它尝试重新连接的时候绑定的资源不能(MUST NOT)和前一个会话的资源相同，而是必须选择一个不同的资源; 详见 [[RFC6120#资源绑定|第7章]].&lt;br /&gt;
&lt;br /&gt;
=====connection-timeout=====&lt;br /&gt;
&lt;br /&gt;
如果一方有理由相信另一方永久地失去了通过某个流进行通讯的能力，它可以关闭这个流. 有很多办法可以查觉到对方丧失通讯能力, 类似 [[RFC6120#关闭流|4.4]] 所述的空格符保持连接, 定义于 [[RFC6120#提示性备注|XEP‑0199]] 的XMPP级的ping, 以及定义于[[RFC6120#提示性备注|XEP‑0198]] 的XMPP流管理.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
P: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;connection-timeout&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:互操作性备注: RFC 3920指出，如果在一段时间内对端在某个流上没有产生任何流量，则使用&amp;lt;connection-timeout/&amp;gt;流错误([[RFC6120#connection-timeout|4.9.3.4]]). 那种行为已经不推荐了; 替代办法是, 只在已连接客户端或对端服务器不响应该流发送的数据时才使用该错误.&lt;br /&gt;
&lt;br /&gt;
=====host-gone=====&lt;br /&gt;
&lt;br /&gt;
在初始化流头中提供的'to'属性的值对应的完整合法域名(FQDN)不再由接收方实体提供服务.&lt;br /&gt;
&lt;br /&gt;
(以下例子中, 当连接到&amp;quot;im.example.com&amp;quot;服务器时,对端指定了一个'to'地址&amp;quot;foo.im.example.com&amp;quot;， 但是这个服务器不再为那个地址提供服务了.) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
P: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='example.net'&lt;br /&gt;
       to='foo.im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:server'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='g4qSvGvBxJ+xeAd7QKezOQJFFlw='&lt;br /&gt;
       to='example.net'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:server'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;host-gone&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====host-unknown=====&lt;br /&gt;
&lt;br /&gt;
初始流头中提供的'to'属性的值不对应接收方实体所服务的合法域名(FQDN).&lt;br /&gt;
&lt;br /&gt;
(在下例中, 对端连接到&amp;quot;im.example.com&amp;quot;服务器的时候指定了一个'to'地址&amp;quot;example.org&amp;quot;, 但是该服务器不知道这个地址.) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
P: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='example.net'&lt;br /&gt;
       to='example.org'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:server'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='g4qSvGvBxJ+xeAd7QKezOQJFFlw='&lt;br /&gt;
       to='example.net'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:server'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;host-unknown&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====improper-addressing=====&lt;br /&gt;
&lt;br /&gt;
在两服务器之间发送的节缺少'to'或'from'属性, 这个'from'或'to'属性没有值, 或它的值违反了XMPP地址[[RFC6120#常规备注|XMPP‑ADDR]]的规则 .&lt;br /&gt;
&lt;br /&gt;
(在下例中, 对端在服务器-服务器流中发送了一个不包含'to'地址的节.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
P: &amp;lt;message from='juliet@im.example.com'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;Wherefore art thou?&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;improper-addressing&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====internal-server-error=====&lt;br /&gt;
&lt;br /&gt;
服务器配置错误或其他内部错误导致它无法服务于该流. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;internal-server-error&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====invalid-from=====&lt;br /&gt;
&lt;br /&gt;
当 (1) 在两个服务器使用SASL或服务器回拨, 或 (2) 在客户端和服务器通过SASL验证和资源绑定的时候,协商时的'from'属性提供的数据不匹配已授权的JID或合法的域名.&lt;br /&gt;
&lt;br /&gt;
(在下例中, 一个仅被授权为&amp;quot;example.net&amp;quot;的对端尝试以地址&amp;quot;example.org&amp;quot;发送节.) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
P: &amp;lt;message from='romeo@example.org' to='juliet@im.example.com'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;Neither, fair saint, if either thee dislike.&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;invalid-from&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====invalid-namespace=====&lt;br /&gt;
&lt;br /&gt;
流命名空间的名字不是&amp;quot;http://etherx.jabber.org/streams&amp;quot; (见 [[RFC6120#XML命名空间和前缀|11.2]]) 或不支持把内容命名空间声明为缺省命名空间 (例如, 不同于&amp;quot;jabber:client&amp;quot;或&amp;quot;jabber:server&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
(下例中, 客户端为流指定了一个命名空间'http://wrong.namespace.example.org/'.) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://wrong.namespace.example.org/'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;invalid-namespace&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====invalid-xml=====&lt;br /&gt;
&lt;br /&gt;
实体通过该流发送了非法的XML到一个执行验证的服务器上(见 [[RFC6120#验证|11.4]]).&lt;br /&gt;
&lt;br /&gt;
(下例中, 对端尝试发送一个类型为&amp;quot;subscribe&amp;quot;的IQ节, 但是XML schema没有这个'类型'的属性.) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
P: &amp;lt;iq from='example.net'&lt;br /&gt;
       id='l3b1vs75'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       type='subscribe'&amp;gt;&lt;br /&gt;
     &amp;lt;ping xmlns='urn:xmpp:ping'/&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;invalid-xml&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====not-authorized=====&lt;br /&gt;
&lt;br /&gt;
实体尝试在流被验证之前发送XML节或其他出站数据, 或没有被授权执行一个和流协商有关的动作; 接收方实体在发送流错误之前不能(MUST NOT)处理这些数据.&lt;br /&gt;
&lt;br /&gt;
(下例中, 客户端尝试在被服务器验证前发送XML节.) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
C: &amp;lt;message to='romeo@example.net'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;Wherefore art thou?&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;not-authorized&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====not-well-formed=====&lt;br /&gt;
&lt;br /&gt;
初始化实体发送了违反[[RFC6120#常规备注|XML]]或[[RFC6120#常规备注|XML‑NAMES]]的&amp;quot;良好格式&amp;quot;规则的XML.&lt;br /&gt;
&lt;br /&gt;
(下例中, 客户端发送一个命名空间格式错误的XMPP消息.) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&amp;gt;&lt;br /&gt;
     &amp;lt;foo:body&amp;gt;What is this foo?&amp;lt;/foo:body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;not-well-formed&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:互操作性备注: 在RFC 3920中, 这个错误条件的名字是 &amp;quot;xml-not-well-formed&amp;quot; 而不是 &amp;quot;not-well-formed&amp;quot;. 改名是因为元素名 &amp;lt;xml-not-well-formed/&amp;gt; 违反了[[RFC6120#常规备注|XML]]第三章的约束 &amp;quot;以 (('X'|'x')('M'|'m')('L'|'l')) 打头的名字是保留给本协议的这个或下个版本的标准化用的&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=====policy-violation=====&lt;br /&gt;
&lt;br /&gt;
实体违反一些本地服务策略 (例如, 一个节超出了配置的大小限制); 服务器可以选择在 &amp;lt;text/&amp;gt; 元素里或在一个应用特有的条件元素中指定这个策略.&lt;br /&gt;
&lt;br /&gt;
(下例中, 客户端发送了一个据服务器的本地服务策略看来过大的XMPP消息.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message to='juliet@im.example.com' id='foo'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;[ ... the-emacs-manual ... ]&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;policy-violation&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
     &amp;lt;stanza-too-big xmlns='urn:xmpp:errors'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====remote-connection-failed=====&lt;br /&gt;
&lt;br /&gt;
服务器不能正确地连接到一个需要验证或授权的远程实体 (例如, 在和服务器回拨[[RFC6120#提示性备注|XEP-0220]]相关的特定场景); 当发生这个错误的是XMPP服务提供商有管理员权限的域时候，这个条件不被使用, 那种情况下更适合使用 &amp;lt;internal-server-error/&amp;gt; 条件.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;remote-connection-failed&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====reset=====&lt;br /&gt;
&lt;br /&gt;
服务器在下列情况下关闭流，如提供了新的流特性(特别是关系安全的), 如为流建立安全上下文的密钥或者证书过期或在流的声明周期中被收回([[RFC6120#检查长连接流的证书|13.7.2.3), 如TLS序列号已经封装了([[RFC6120#TLS重新协商|5.3.5]]), 等等. reset适用于流以及该流(例如, 通过TLS和 SASL)建立的的任何安全上下文, 这意味着新的流的加密和验证需要再次协商(例如, 不能使用TLS会话恢复了).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;reset&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====resource-constraint=====&lt;br /&gt;
&lt;br /&gt;
服务器缺乏必要系统资源来服务于这个流.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;resource-constraint&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====restricted-xml=====&lt;br /&gt;
&lt;br /&gt;
实体尝试发送受限的XML特性，例如 注释, 处理指令, DTD子集, 或XML实体参考(见 [[RFC6120#XML限制|11.1]]).&lt;br /&gt;
&lt;br /&gt;
(下例中, 客户端发送一个包含XML注释的XMPP消息.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message to='juliet@im.example.com'&amp;gt;&lt;br /&gt;
     &amp;lt;!--&amp;lt;subject/&amp;gt;--&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;This message has no subject.&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;restricted-xml&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====see-other-host=====&lt;br /&gt;
&lt;br /&gt;
服务器将不提供服务给初始化实体，但是重定向到同一个服务提供商管理控制下的另一台主机. 服务器返回的 &amp;lt;see-other-host/&amp;gt; 元素的XML字符串数据必须指定用来连接的替代的合法域名(FQDN)或IP地址, 它必须是一个合法的域部分或一个域部分加上一个端口号(通过&amp;quot;域名:端口号&amp;quot;中的':'字符来区分). 如果域部分和源域相同,或和派生域相同, 或解析出来的IPv4或IPv6地址和初始化实体原先连接的地址相同(只是端口号不同), 那么初始化实体应该简单地重新连接那个地址. (IPv6地址的格式必须遵循[[RFC6120#常规备注|IPv6‑ADDR]], 它包括如 [[RFC6120#常规备注|URI]] 所定义的，把IPv6地址封闭在方括号'[' 和 ']'里.) 否则, 初始化实体必须解析&amp;lt;see-other-host/&amp;gt;元素中指定的合格域名(FQDN),如 [[RFC6120#|解析合格域名3.2]]所述.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;see-other-host&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'&amp;gt;&lt;br /&gt;
       [2001:41D0:1:A49b::1]:9222&lt;br /&gt;
     &amp;lt;/see-other-host&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当协商一个已经被重定向的流时, 初始化实体必须应用和它应用于初次连接时相同的策略 (例如, 一个必须使用TLS的策略), 必须在初始化流头中指定相同的'to'地址, 而且必须使用和初次尝试连接时相同的参考标识符来检查新地址的标识符 (符合 [[RFC6120#常规备注|TLS‑CERTS]]). 即使接收方在流的保密和信任关系建立之前返回一个&amp;lt;see-other-host/&amp;gt;错误(从而产生 拒绝服务 攻击的可能性), 事实上初始化实体需要基于相同的参考标识符来检查XMPP服务的标识符，这意味着初始化实体将不会连接到一个恶意的实体. 为了避免 拒绝服务 攻击, (a) 在流的保密和信任关系由TLS或相当的安全层(例如 SASL GSSAPI 机制)保护起来立之前, 接收方实体不应该以&amp;lt;see-other-host/&amp;gt;流错误关闭流, 并且 (b) 只有当它已经被接收方实体验证了, 接收方才可以有一个下述的重定向策略. 另外, 初始化实体在特定数量的成功重定向之后应该放弃尝试连接(例如, 最少2次但不超过5次).&lt;br /&gt;
&lt;br /&gt;
=====system-shutdown=====&lt;br /&gt;
&lt;br /&gt;
服务器正在关闭且所有活跃的流正在被关闭.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;system-shutdown&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====undefined-condition=====&lt;br /&gt;
&lt;br /&gt;
这个错误条件不是预定义的条件列表中的一个; 这个错误应该不被使用，除非结合一个应用特有的条件.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;undefined-condition&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
     &amp;lt;app-error xmlns='http://example.org/ns'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====unsupported-encoding=====&lt;br /&gt;
&lt;br /&gt;
初始化实体给流使用的编码不被服务器支持(见 [[RFC6120#字符编码|11.6]]) 或没有正确地对流进行编码 (例如, 违反了 [[RFC6120#常规备注|UTF‑8]] 编码规则).&lt;br /&gt;
&lt;br /&gt;
(下例中, 客户端试图使用UTF-16编码而不是UTF-8.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0' encoding='UTF-16'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;unsupported-encoding&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====unsupported-feature=====&lt;br /&gt;
&lt;br /&gt;
接收方实体声明了一个 强制协商 的流特性，但是初始化实体不支持它, 并且提不出其他等价于不支持特性的 强制协商 特性.&lt;br /&gt;
&lt;br /&gt;
(下例中, 接收方实体要求一个example特性, 但是初始化实体不支持这个特性.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
Rs: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;example xmlns='urn:xmpp:example'&amp;gt;&lt;br /&gt;
       &amp;lt;required/&amp;gt;&lt;br /&gt;
     &amp;lt;/example&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;unsupported-feature&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====unsupported-stanza-type=====&lt;br /&gt;
&lt;br /&gt;
初始化实体发送的流的顶级子元素不被服务器支持, 要么是因为接收方实体不理解命名空间要么因为接收方实体不理解适用的命名空间的元素名(可能是声明为缺省命名空间的内容命名空间).&lt;br /&gt;
&lt;br /&gt;
(下例中, 客户端尝试发送一个由'jabber:client'命名空间限定的顶级子元素 &amp;lt;pubsub/&amp;gt; , 但是那个命名空间的schema没有定义这个元素.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;pubsub xmlns='jabber:client'&amp;gt;&lt;br /&gt;
     &amp;lt;publish node='princely_musings'&amp;gt;&lt;br /&gt;
       &amp;lt;item id='ae890ac52d0df67ed7cfdf51b644e901'&amp;gt;&lt;br /&gt;
         &amp;lt;entry xmlns='http://www.w3.org/2005/Atom'&amp;gt;&lt;br /&gt;
           &amp;lt;title&amp;gt;Soliloquy&amp;lt;/title&amp;gt;&lt;br /&gt;
           &amp;lt;summary&amp;gt;&lt;br /&gt;
To be, or not to be: that is the question:&lt;br /&gt;
Whether 'tis nobler in the mind to suffer&lt;br /&gt;
The slings and arrows of outrageous fortune,&lt;br /&gt;
Or to take arms against a sea of troubles,&lt;br /&gt;
And by opposing end them?&lt;br /&gt;
           &amp;lt;/summary&amp;gt;&lt;br /&gt;
           &amp;lt;link rel='alternate' type='text/html'&lt;br /&gt;
                 href='http://denmark.example/2003/12/13/atom03'/&amp;gt;&lt;br /&gt;
           &amp;lt;id&amp;gt;tag:denmark.example,2003:entry-32397&amp;lt;/id&amp;gt;&lt;br /&gt;
           &amp;lt;published&amp;gt;2003-12-13T18:30:02Z&amp;lt;/published&amp;gt;&lt;br /&gt;
           &amp;lt;updated&amp;gt;2003-12-13T18:30:02Z&amp;lt;/updated&amp;gt;&lt;br /&gt;
         &amp;lt;/entry&amp;gt;&lt;br /&gt;
       &amp;lt;/item&amp;gt;&lt;br /&gt;
     &amp;lt;/publish&amp;gt;&lt;br /&gt;
   &amp;lt;/pubsub&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;unsupported-stanza-type&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====unsupported-version=====&lt;br /&gt;
&lt;br /&gt;
由初始化实体在流头中提供的'version'属性指定的XMPP版本不被服务器支持.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='11.0'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
   &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;unsupported-version&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====应用特有的条件====&lt;br /&gt;
&lt;br /&gt;
大家知道, 应用可以在错误元素中包含一个适当的命名空间子元素来提供应用特有的错误信息. 应用特有的元素应该补充或进一步限定一个已定义的元素. 因此, &amp;lt;error/&amp;gt; 元素将包含两个或三个子元素.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;&lt;br /&gt;
       My keyboard layout is:&lt;br /&gt;
&lt;br /&gt;
       QWERTYUIOP{}|&lt;br /&gt;
       ASDFGHJKL:&amp;quot;&lt;br /&gt;
       ZXCVBNM&amp;lt;&amp;gt;?&lt;br /&gt;
     &amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
     &amp;lt;not-well-formed&lt;br /&gt;
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
     &amp;lt;text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'&amp;gt;&lt;br /&gt;
       Some special application diagnostic information!&lt;br /&gt;
     &amp;lt;/text&amp;gt;&lt;br /&gt;
     &amp;lt;escape-your-data xmlns='http://example.org/ns'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===简化的流示例===&lt;br /&gt;
&lt;br /&gt;
这一仗包含两个客户端和服务器之间基于流的连接的高度简化的例子; 这些例子的目的是说明迄今为止介绍的那些概念, 但是读者需要注意这些例子省略了一些细节 (更完整的例子见 [[RFC6120#详细的例子|第9章]]).&lt;br /&gt;
&lt;br /&gt;
一个基本的连接:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[ ... stream negotiation ... ]&lt;br /&gt;
&lt;br /&gt;
C:   &amp;lt;message from='juliet@im.example.com/balcony'&lt;br /&gt;
              to='romeo@example.net'&lt;br /&gt;
              xml:lang='en'&amp;gt;&lt;br /&gt;
       &amp;lt;body&amp;gt;Art thou not Romeo, and a Montague?&amp;lt;/body&amp;gt;&lt;br /&gt;
     &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S:   &amp;lt;message from='romeo@example.net/orchard'&lt;br /&gt;
              to='juliet@im.example.com/balcony'&lt;br /&gt;
              xml:lang='en'&amp;gt;&lt;br /&gt;
       &amp;lt;body&amp;gt;Neither, fair saint, if either thee dislike.&amp;lt;/body&amp;gt;&lt;br /&gt;
     &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
C: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
连接坏了:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='juliet@im.example.com'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;?xml version='1.0'?&amp;gt;&lt;br /&gt;
   &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='++TR84Sm6A3hnt3Q065SnAbbk3Y='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[ ... stream negotiation ... ]&lt;br /&gt;
&lt;br /&gt;
C:   &amp;lt;message from='juliet@im.example.com/balcony'&lt;br /&gt;
              to='romeo@example.net'&lt;br /&gt;
              xml:lang='en'&amp;gt;&lt;br /&gt;
       &amp;lt;body&amp;gt;No closing tag!&lt;br /&gt;
     &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:error&amp;gt;&lt;br /&gt;
    &amp;lt;not-well-formed&lt;br /&gt;
        xmlns='urn:ietf:params:xml:ns:xmpp-streams'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:error&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
更多详细的例子请到[[RFC6120#详细的例子|第9章]] .&lt;br /&gt;
&lt;br /&gt;
==STARTTLS协商==&lt;br /&gt;
===STARTTLS基础===&lt;br /&gt;
&lt;br /&gt;
XMPP包含了一个方法来保护流的安全使其免于被篡改和窃听. 这个通道加密的方法使用传输层安全 [[RFC6120#常规备注|TLS]] 协议, 特别是&amp;quot;STARTTLS&amp;quot;扩展，这个扩展是以 [[RFC6120#提示性备注|USINGTLS]]中描述的 [[RFC6120#提示性备注|IMAP]], [[RFC6120#提示性备注|POP3]], 和 [[RFC6120#提示性备注|ACAP]] 协议中的类似扩展为蓝本的. STARTTLS扩展的XML命名空间是 'urn:ietf:params:xml:ns:xmpp-tls'.&lt;br /&gt;
&lt;br /&gt;
===支持===&lt;br /&gt;
&lt;br /&gt;
在XMPP客户端和服务器的实现中必须支持STARTTLS. 一个给定布署的管理员可以指定 客户端-服务器通讯 和/或 服务器-服务器通讯 中TLS是强制协商的. 一个初始化实体应该在开始SASL验证之前使用TLS保护和接收方之间的流的安全.&lt;br /&gt;
&lt;br /&gt;
===流协商规则===&lt;br /&gt;
====强制协商====&lt;br /&gt;
&lt;br /&gt;
如果接收方实体只声明了STARTTLS特性或接收方实体包含了[[RRC6120#流头和流特性交换|5.4.1]]所述的&amp;lt;required/&amp;gt;子元素, 双方必须确保TLS是强制协商的. 如果TLS是强制协商的, 在流协商过程的初始化阶段接收方实体应该不(SHOULD NOT)声明支持任何STARTTLS以外的流特性, 因为在XMPP的层顺序中更多流特性可能依赖TLS的预先协商 (例如, 由接收方实体提供的特定的SASL机制将依赖于TLS是否完成协商).&lt;br /&gt;
&lt;br /&gt;
====重启====&lt;br /&gt;
&lt;br /&gt;
在TLS协商之后, 双方必须重启这个流.&lt;br /&gt;
&lt;br /&gt;
====数据格式====&lt;br /&gt;
&lt;br /&gt;
当STARTTLS协商时, 实体们不能(MUST NOT)在XML元素之间发送任何空格符号 (即, 由初始化实体发送的从'urn:ietf:params:xml:ns:xmpp-tls'命名空间限定的顶级&amp;lt;starttls/&amp;gt;元素的最后的字符, 到由接收方实体发送的'urn:ietf:params:xml:ns:xmpp-tls'命名空间限定的顶级&amp;lt;proceed/&amp;gt;元素的最后的字符). 这个禁令帮助确保适当的安全字节精度. 任何出现在本文提供的STARTTLS例子中的空格只是为了提高可读性.&lt;br /&gt;
&lt;br /&gt;
====TLS和SASL协商的顺序====&lt;br /&gt;
&lt;br /&gt;
如果初始化实体选择使用TLS, STARTTLS协商必须在[[RFC6120#SASL协商|SASL协商]]之前完成; 这个协商顺序对于帮助保护SASL协商期间发送的验证信息是必要的, 同时尽可能使用基于预先的TLS协商中提供的证书(或其他证件)的SASL EXTERNAL机制.&lt;br /&gt;
&lt;br /&gt;
====TLS重协商====&lt;br /&gt;
&lt;br /&gt;
TLS协议允许双方在一个 受TLS保护 的通道里初始化一个新的握手来建立新的加密参数(见 [[RFC6120#常规备注|TLS‑NEG]]). 最常提及的案例如下:&lt;br /&gt;
&lt;br /&gt;
# 刷新密钥&lt;br /&gt;
# 如[[RFC6120#常规备注|TLS]]的6.1节所述封装TLS序列号.&lt;br /&gt;
# 在受保护的通道上先完成服务器验证再完成客户端验证以保护客户端证书.&lt;br /&gt;
&lt;br /&gt;
因为在XMPP中建立一个流的代价相对低廉, 对于前面两个案例推荐使用XMPP流重置(如 [[RFC6120#reset|4.9.3.16]]) 而不是执行TLS重协商.&lt;br /&gt;
&lt;br /&gt;
第三个案例在TLS客户端(也可能是一个XMPP服务器)递交TLS证书给服务器时提高了安全特性. 如果和一个未验证的TLS服务器交换这类证书可能泄露隐私信息, 先完成让TLS客户端验证TLS服务器的TLS协商，再完成让TLS服务器验证TLS客户端的TLS协商，是适当的. 然而, 这个案例极为罕见，因为由一个扮演TLS客户端角色的XMPP服务器或XMPP客户端对外展现的证书几乎总是公开的(即, PKIX 证书), 所以在验证作为TLS服务器的XMPP服务器之前提供那些证书通常将不会泄露隐私信息.&lt;br /&gt;
&lt;br /&gt;
作为结果, 鼓励实现者在他们的软件中支持TLS重协商之前小心地权衡它的开销和好处, 不鼓励扮演TLS客户端的XMPP实体尝试TLS重协商，除非已知要在TLS协商中发送的证书(或其他证件信息)是私有的.&lt;br /&gt;
&lt;br /&gt;
对TLS重协商的支持是严格可选的. 然而, 支持TLS重协商的实现们必须实现和使用 TLS重协商扩展 [[RFC6120#常规备注|TLS‑NEG]].&lt;br /&gt;
&lt;br /&gt;
如果一个不支持TLS重协商的实体察觉到一个重协商尝试, 那么它必须立刻关闭相关的TCP连接而不要返回任何流错误(因为这个违规可能发生在TLS层, 而不是XMPP层, 详见 [[RFC6120#层的顺序|13.3]]).&lt;br /&gt;
&lt;br /&gt;
如果一个支持TLS重协商的实体察觉到一个未使用 TLS重协商扩展 [[RFC6120#常规备注|TLS‑NEG]] 的TLS重协商尝试 , 那么它必须立刻关闭相关的TCP连接而不要返回任何流错误(因为这个违规可能发生在TLS层, 而不是XMPP层, 详见 [[RFC6120#层的顺序|13.3]]).&lt;br /&gt;
&lt;br /&gt;
====TLS扩展====&lt;br /&gt;
&lt;br /&gt;
一个流的双方可以在它自己的TLS协商时包含任何TLS扩展. 这是TLS层的事情, 不是XMPP层.&lt;br /&gt;
&lt;br /&gt;
===过程===&lt;br /&gt;
====流头和流特性交换====&lt;br /&gt;
&lt;br /&gt;
初始化实体如[[RFC6120#TCP绑定|第三章]]所述解析接收实体的合格域名(FQDN), 打开一个到解析的IP地址和声明的端口的TCP连接, 并发送一个初始化流头给接收方流头.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;stream:stream&lt;br /&gt;
     from='juliet@im.example.com'&lt;br /&gt;
     to='im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
接收方实体必须通过初始化实体打开的那个TCP连接发送一个应答流头给初始化实体.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:stream&lt;br /&gt;
     from='im.example.com'&lt;br /&gt;
     id='t7AMCin9zjMNwQKDnplntZPIDEI='&lt;br /&gt;
     to='juliet@im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
接着接收方实体必须发送流特性给初始化实体. 如果接收方实体支持TLS, 流特性必须包含一个支持STARTTLS协商的声明, 即, 一个由'urn:ietf:params:xml:ns:xmpp-tls'命名空间限定的&amp;lt;starttls/&amp;gt;元素.&lt;br /&gt;
&lt;br /&gt;
如果接收方实体认为STARTTLS协商是强制协商的, &amp;lt;starttls/&amp;gt;元素必须包含一个空的&amp;lt;required/&amp;gt;子元素.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'&amp;gt;&lt;br /&gt;
       &amp;lt;required/&amp;gt;&lt;br /&gt;
     &amp;lt;/starttls&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====STARTTLS协商的初始化====&lt;br /&gt;
=====STARTTLS命令=====&lt;br /&gt;
&lt;br /&gt;
为了开始STARTTLS协商, 初始化实体发出STARTTLS指令(即, 一个由'urn:ietf:params:xml:ns:xmpp-tls'命名空间限定的&amp;lt;starttls/&amp;gt;元素)来指示接收方实体它希望开始一次STARTTLS协商以保护流.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
接收方实体必须以由'urn:ietf:params:xml:ns:xmpp-tls'命名空间限定的&amp;lt;proceed/&amp;gt;元素(继续进行的情况下)或&amp;lt;failure/&amp;gt;元素(失败的情况下)回复. &lt;br /&gt;
&lt;br /&gt;
=====失败的情况=====&lt;br /&gt;
&lt;br /&gt;
如果发生失败的情况, 接收方实体必须返回一个由'urn:ietf:params:xml:ns:xmpp-tls'命名空间限定的&amp;lt;failure/&amp;gt;元素, 关闭这个XML流, 并且终止当前的TCP连接.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
导致失败的情况包含但不限于以下几种:&lt;br /&gt;
&lt;br /&gt;
:# 初始化实体发送了一个异常的STARTTLS命令.&lt;br /&gt;
:# 接收方实体在它的流特性中不提供STARTTLS特性 .&lt;br /&gt;
:# 接收方实体因为内部错误而无法完成STARTTLS协商.&lt;br /&gt;
&lt;br /&gt;
:提示性备注: STARTTLS失败不会由TLS错误触发，例如 坏证书(bad_certificate)或 握手失败(handshake_failure), 它是由TLS协商本身生成和处理的，参见[[RFC6120#常规备注|TLS]].&lt;br /&gt;
&lt;br /&gt;
如果发生了失败的情况, 初始化实体可以尝试重连，参见 [[RFC6120#重连|3.3]].&lt;br /&gt;
&lt;br /&gt;
=====继续进行的情况=====&lt;br /&gt;
&lt;br /&gt;
如果发生继续进行的情况, 接收方实体必须返回一个由'urn:ietf:params:xml:ns:xmpp-tls'命名空间限定的&amp;lt;proceed/&amp;gt;元素.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
接收方实体在发送了&amp;lt;proceed/&amp;gt;元素的关闭字符'&amp;gt;'之后必须认为TLS协商已经立刻开始了. 初始化实体在从接收方实体接收到&amp;lt;proceed/&amp;gt;元素的关闭字符'&amp;gt;'之后必须认为TLS协商已经立刻开始了.&lt;br /&gt;
&lt;br /&gt;
实体现在继续进行TLS协商，如下一节所述.&lt;br /&gt;
&lt;br /&gt;
====TLS协商====&lt;br /&gt;
=====规则=====&lt;br /&gt;
&lt;br /&gt;
为了在TCP连接上完成TLS协商, 实体们必须跟随以下定义于[[RFC6120#常规备注|TLS]]的过程 .&lt;br /&gt;
&lt;br /&gt;
以下规则适用于:&lt;br /&gt;
&lt;br /&gt;
:# 实体们在TLS协商完成之前不能(MUST NOT)发送任何其他XML数据.&lt;br /&gt;
:# 当使用定义于[[RFC6120#强制实现的TLS和SASL技术|13.8]]的任何强制实现(MTI)的密码组时, 接收方实体必须出示一个证书.&lt;br /&gt;
:# 所以证书相互验证是有可能的, 接收方实体应该发送一个证书请求给初始化实体, 而初始化实体应该发送一个证书给接收方实体(但是由于隐私的原因可能选择在接收方实体已经被初始化实体验证之后才发送自己的证书).&lt;br /&gt;
:# 接收方实体应该基于包含在初始化流头中的'to'属性中的域部分选择哪个证书来展示(本质上, 这个域部分功能上等同于服务器名称指示 定义于[[RFC6120#提示性备注|TLS‑EXT]]).&lt;br /&gt;
:# 为了确定TLS协商是否成功, 初始化实体必须尝试根据[[RFC6120#证书验证|13.7.2]]定义的证书验证程序来验证接收方实体的证书.&lt;br /&gt;
:# 如果初始化实体出示了一个证书, 接收方实体也必须尝试根据[[RFC6120#证书验证|13.7.2]]定义的证书验证程序来验证初始化实体的证书.&lt;br /&gt;
:# 随着TLS协商成功, 所有双方传送的更多的数据必须被协商的算法，密钥和秘密来保护(即, 加密, 完整性保护, 或都依赖于使用的密码组).&lt;br /&gt;
&lt;br /&gt;
:安全警告: 关于[[RFC6120#强制实现的TLS和SASL技术|13.8]]提到的密码组必须被TLS所支持; 自然的, 其他密码组也可以被支持.&lt;br /&gt;
&lt;br /&gt;
=====TLS失败=====&lt;br /&gt;
&lt;br /&gt;
如果TLS协商结果是失败, 接收方实体必须终止该TCP连接.&lt;br /&gt;
&lt;br /&gt;
在终止该TCP连接之前,接收方实体不能(MUST NOT)发送关闭标签&amp;lt;/stream&amp;gt;(因为失败可能发生在TLS层, 而不是XMPP层，参见[[RFC6120#层的顺序|13.3]]所述).&lt;br /&gt;
&lt;br /&gt;
初始化实体可以如[[RFC6120#重连|3.3]]所述尝试重连, 尝试使用或不使用TLS协商(依照本地服务策略, 用户配置的偏好, 等等).&lt;br /&gt;
&lt;br /&gt;
=====TLS成功=====&lt;br /&gt;
&lt;br /&gt;
如果TLS协商是成功的, 那么实体们必须继续如下步骤.&lt;br /&gt;
&lt;br /&gt;
:1. 初始化实体必须忽略TLS生效之前在TCP上的不安全情况下从接收方实体收到的任何信息(例如, 接收方实体的'from'地址或从接收方实体收到的流ID以及流特性).&lt;br /&gt;
:2. 接收方实体必须忽略TLS生效之前在TCP上的不安全情况下从初始化实体收到的任何信息(例如, 初始化实体的'from'地址).&lt;br /&gt;
:3. 初始化实体必须通过加密的连接发送一个新的初始化流头给接收方实体(如[[RFC6120#重启|4.3.3]]定义的, 在发送新的初始化流头之前初始化实体必须发送一个关闭标签&amp;lt;/stream&amp;gt;, 因为接收方实体和初始化实体必须确定旧的流在TLS协商成功之后被替代了).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
    I: &amp;lt;stream:stream&lt;br /&gt;
         from='juliet@im.example.com'&lt;br /&gt;
         to='im.example.com'&lt;br /&gt;
         version='1.0'&lt;br /&gt;
         xml:lang='en'&lt;br /&gt;
         xmlns='jabber:client'&lt;br /&gt;
         xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:4. 接收方实体必须通过加密连接以一个新的应答流头来应答(为此它必须生成一个新的流ID而不是重用旧的流ID).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
    R: &amp;lt;stream:stream&lt;br /&gt;
         from='im.example.com'&lt;br /&gt;
         id='vgKi/bkYME8OAj4rlXMkpucAqe4='&lt;br /&gt;
         to='juliet@im.example.com'&lt;br /&gt;
         version='1.0'&lt;br /&gt;
         xml:lang='en'&lt;br /&gt;
         xmlns='jabber:client'&lt;br /&gt;
         xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:5. 接收方实体也必须发送流特性给初始化实体, 不能(MUST NOT)包含STARTTLS特性但是应该包含SASL流特性，如[[RFC6120#SASL协商|第六章]](特别是[[RFC6120#流头和流特性交换|6.4.1]]中关于为什么不在这里提供SASL流特性的新的原因).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
    R: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
         &amp;lt;mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
           &amp;lt;mechanism&amp;gt;EXTERNAL&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
           &amp;lt;mechanism&amp;gt;SCRAM-SHA-1-PLUS&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
           &amp;lt;mechanism&amp;gt;SCRAM-SHA-1&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
           &amp;lt;mechanism&amp;gt;PLAIN&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
         &amp;lt;/mechanisms&amp;gt;&lt;br /&gt;
       &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==SASL协商==&lt;br /&gt;
===SASL基础===&lt;br /&gt;
&lt;br /&gt;
XMPP包含了一个某种意义上XMPP特有的简单验证和安全层协议(见[[RFC6120#常规备注|SASL]])用于验证一个流. SASL提供一个一般化的方法来给基于连接的协议添加验证支持, 而XMPP遵照[[RFC6120#常规备注|SASL]]的解析要求来使用SASL的XML命名空间解析. SASL扩展的XML命名空间名称是'urn:ietf:params:xml:ns:xmpp-sasl'.&lt;br /&gt;
&lt;br /&gt;
===支持===&lt;br /&gt;
&lt;br /&gt;
XMPP客户端和服务器必须支持SASL协商.&lt;br /&gt;
&lt;br /&gt;
===流协商规则===&lt;br /&gt;
====强制协商====&lt;br /&gt;
&lt;br /&gt;
一个流双方bxu确认SASL是强制协商的.&lt;br /&gt;
&lt;br /&gt;
====重启====&lt;br /&gt;
&lt;br /&gt;
在SASL协商之后, 双方必须重启该流.&lt;br /&gt;
&lt;br /&gt;
====机制推荐====&lt;br /&gt;
&lt;br /&gt;
任何将要扮演SASL客户端或SASL服务器的实体必须对于该客户端或该服务器维护一个它推荐的SASL机制的有序列表, 这个列表的顺序是根据本地策略或用户配置来的(它的顺序应该是根据验证能力越强排在越靠前). 初始化实体必须独立于接收方实体的推荐顺序来维护它自己的推荐顺序. 客户端必须以它自己的推荐顺序来尝试SASL机制. 例如, 如果服务器提供的顺序列表是&amp;quot;PLAIN SCRAM-SHA-1 GSSAPI&amp;quot; 或 &amp;quot;SCRAM-SHA-1 GSSAPI PLAIN&amp;quot; 而客户端的顺序列表是 &amp;quot;GSSAPI SCRAM-SHA-1&amp;quot;, 客户端必须首先尝试 GSSAPI 然后尝试 SCRAM-SHA-1 而不能(MUST NOT)尝试 PLAIN (因为 PLAIN 不在它的列表中).&lt;br /&gt;
&lt;br /&gt;
====机制提供====&lt;br /&gt;
&lt;br /&gt;
如果接收方实体在它接受特定的SASL机制之前确定[[RFC6120#STARTTLS|TLS协商]]是强制协商, 它不能(MUST NOT)在完成TLS协商之前在它的可用SASL机制列表中声明那个机制.&lt;br /&gt;
&lt;br /&gt;
如果发生以下两种情况，接收方实体应该提供 SASL EXTERNAL 机制，:&lt;br /&gt;
&lt;br /&gt;
:# 当初始化实体在TLS协商中出示了一个证书，这个证书被接收方实体接受了，接收方根据本地服务策略把它用于强身份验证(例如, 因为证书没有过期，没有撤销，并且被锚定到一个接收方实体信任的root账户).&lt;br /&gt;
:# 接收方实体期望初始化实体能够验证和授权这个证书所提供的身份; 在服务器-服务器流的情形下, 接收方实体可能有这样一个预期，因为初始化实体的证书所展示的DNS域名和初始化流头中相应的'from'属性是匹配的, 这里使用[[RFC6120#常规备注|TLS‑CERTS]]的匹配规则; 在客户端-服务器流的情形下, 接收方实体可能有这样一个预期，是因为在初始化实体的证书中展示的纯JID和在这个服务器上注册的一个用户帐号匹配，或者因为其他包含在初始化实体证书中的信息和被允许使用该服务器访问XMPP网络的某个实体相匹配.&lt;br /&gt;
&lt;br /&gt;
无论如何, 接收方实体在其他情况下也一样可以提供 SASL EXTERNAL 机制.&lt;br /&gt;
&lt;br /&gt;
当接收方实体提供 SASL EXTERNAL 机制, 接收方实体应该首先列出它提供的SASL机制的 EXTERNAL 机制列表，而初始化实体应该尝试首先使用EXTERNAL机制来进行SASL协商(这个选择往往会增加双方相互进行证书验证的可能性).&lt;br /&gt;
&lt;br /&gt;
[[RFC6120#强制协商的TLS和SASL技术|13.8]]定义了必须支持的SASL机制; 自然的, 也一样可以支持其他的SASL机制.&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 在XMPP的上下文中使用SASL的最佳实践，使用ANONYMOUS机制请参考[[RFC6120#提示性备注|XEP‑0175]]，使用EXTERNAL机制请参考[[RFC6120#提示性备注|XEP‑0178]].&lt;br /&gt;
&lt;br /&gt;
====数据格式====&lt;br /&gt;
&lt;br /&gt;
以下数据格式规则适用于SASL协商:&lt;br /&gt;
&lt;br /&gt;
:# 当SASL协商时, 实体不能(MUST NOT)在XML元素之间发送任何空格符号(即, 从初始化实体发送的'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;auth/&amp;gt;顶级元素的最后一个字符, 到接收方实体发送的'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;success/&amp;gt;顶级元素的最后一个字符). 这个禁令帮助确保正确的安全层字节精确度. 本文中任何在SASL例子中出现的这类空格只是为了增加可读性.&lt;br /&gt;
:# 任何包含在XML元素中的XML字符串数据必须使用base 64编码, 这里的编码要坚持[[RFC6120#常规备注|BASE64]]第四章的定义,并且填充位设为零.&lt;br /&gt;
:# 作为[[RFC6120#附录A.4|附录A.4]]下的XML schema中正式指定的 'urn:ietf:params:xml:ns:xmpp-sasl' 命名空间, 接收方实体可以在&amp;lt;mechanisms/&amp;gt;元素中包含一个或多个应用特有的子元素来提供初始化实体使用提供的一个或多个机制进行成功的SASL协商而可能需要的信息; 无论如何, 所有这类元素的语法和语义超出了本协议的范围(见[[RFC6120#提示性备注|XEP‑0233]]的例子).&lt;br /&gt;
&lt;br /&gt;
====安全层====&lt;br /&gt;
&lt;br /&gt;
涉及安全层协商的SASL协商成功后, 初始化实体和接收方实体都必须丢弃任何应用层状态(即, 来自XMPP层的状态, 不包括来自TLS协商或SASL协商的状态).&lt;br /&gt;
&lt;br /&gt;
====简单用户名====&lt;br /&gt;
&lt;br /&gt;
一些SASL机制(例如, CRAM-MD5, DIGEST-MD5, 和 SCRAM) 指定了在这些机制的上下文中使用的验证身份是一个&amp;quot;简单用户名&amp;quot; (见 [[RFC6120#常规备注|SASL]] 的第二章以及 [[RFC6120#提示性备注|SASLPREP]]). 在任何特定的机制或部署中简单用户名的准确格式都是一个本地事务, 并且简单用户名不需要映射到一个应用身份例如JID或JID部件(例如, 本地部分). 无论如何, 在缺乏由服务器提供的本地信息的情况下, 一个XMPP客户端应该假定一个SASL机制的验证身份是等于该用户的JID的本地部分的简单用户名.&lt;br /&gt;
&lt;br /&gt;
====授权身份====&lt;br /&gt;
&lt;br /&gt;
授权身份是一个由初始化实体提供的可选的身份，用来定义它扮演的身份(见[[RFC6120#常规备注|SASL]]第二章). 在客户端-服务器流中, 它大部分被管理员用于代表另一个用户来执行一些管理任务, 而在服务器-服务器流它大部分被用于在XMPP服务上指定一个特定的附加服务(例如, 一个多用户聊天服务器conference.example.com寄宿在example.com的XMPP服务上). 如果初始化实体希望代表另一个实体并且所选择的SASL机制支持授权身份的传输, 该初始化实体必须在SASL协商时提供一个授权身份. 如果初始化实体不希望代表另一个实体的身份, 它不能(MUST NOT)提供授权身份.&lt;br /&gt;
&lt;br /&gt;
在客户端-服务器通讯的情况下, 授权身份的值必须是一个纯JID(&amp;lt;本地部分@域部分&amp;gt;) 而不是一个全JID(&amp;lt;本地部分@域部分/资源部分&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
在服务器-服务器通讯的情况下, 授权身份的值必须且只能是一个域部分(&amp;lt;域部分&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
如果初始化实体在SASL协商时提供一个授权身份, 接收方实体负责验证初始化实体是否事实上被允许承担指定的授权身份; 如果不是, 接收方实体必须返回一个&amp;lt;invalid-authzid/&amp;gt; SASL错误，如 [[RFC6120#invalid-authzid|6.5.6]] 所述.&lt;br /&gt;
&lt;br /&gt;
====领域====&lt;br /&gt;
&lt;br /&gt;
在以特定SASL机制协商的时候接受方实体可以包含一个领域(例如, GSSAPI 和 DIGEST-MD5 机制都允许验证交换的信息中包含领域, 不过其他方式, 如 EXTERNAL, SCRAM, 和 PLAIN 机制不支持这个特性). 如果接受方实体不以一个领域来通讯, 则初始化实体不能(MUST NOT)假定任何领域的存在. 领域必须只被用于验证的目的; 特别是, 初始化实体不能(MUST NOT)尝试从接受方实体提供的领域信息来派生出一个XMPP域部分.&lt;br /&gt;
&lt;br /&gt;
====回合====&lt;br /&gt;
&lt;br /&gt;
[[RFC6120＃常规备注|SASL]] 规定，一个使用中的协议(例如XMPP)可以定义两个方法，这样协议可以节省批准SASL机制的回合:&lt;br /&gt;
&lt;br /&gt;
:# 当SASL客户端(XMPP &amp;quot;初始化实体&amp;quot;) 请求一个验证交换时, 如果使用了适当的SASL机制，它可以在它的请求中包含 &amp;quot;初始化应答&amp;quot; 数据. 在XMPP中, 要实现这一点，就把初始化应答作为XML字符串数据包含在&amp;lt;auth/&amp;gt;元素中.&lt;br /&gt;
:# 在验证交换的结尾, 如果使用了适当的SASL机制，SASL服务器(XMPP &amp;quot;接受方实体&amp;quot;) 可以包含 &amp;quot;成功附带的额外数据&amp;quot;. 在XMPP中, 要实现这一点，就把额外数据作为XML字符串数据包含在&amp;lt;success/&amp;gt;元素中.&lt;br /&gt;
&lt;br /&gt;
为了协议的效率, 要求客户端和服务器必须支持这些方法并且建议使用它们; 无论如何, 客户端和服务器也必须支持低效的模式.&lt;br /&gt;
&lt;br /&gt;
===过程===&lt;br /&gt;
&lt;br /&gt;
SASL协商过程如下. &lt;br /&gt;
&lt;br /&gt;
====流头和流特性交换====&lt;br /&gt;
&lt;br /&gt;
如果SASL协商紧跟在成功的[[RFC6120#STARTTLS协商|STARTTLS协商]]之后, 那么SASL协商发生在已经协商过的受保护的流上. 否则, 初始化实体如[[RFC6120#TCP绑定|第三章]]所述解析接受方实体的完整域名(FQDN), 打开一个到已解析的IP地址的已声明的端口的TCP连接, 并发送一个初始化流头给接受方实体. 在两种情况下, 接受方实体都将从初始化实体接收到一个初始化流.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;stream:stream&lt;br /&gt;
     from='juliet@im.example.com'&lt;br /&gt;
     to='im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当接受方实体处理来自初始化实体的初始化流的时候, 它必须发送一个应答流头给初始化实体(为此它必须生成一个唯一的流ID. 如果TLS协商已经成功, 那么这个流ID必须不同于TLS协商成功之前发送的那个流ID).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:stream&lt;br /&gt;
     from='im.example.com'&lt;br /&gt;
     id='vgKi/bkYME8OAj4rlXMkpucAqe4='&lt;br /&gt;
     to='juliet@im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
接受方实体也必须发送流特性给初始化实体. 流特性应该包含一个声明用来支持SASL协商, 即, 一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;mechanisms/&amp;gt;元素. 典型的，只有三种情况下对SASL协商的支持不需要在这里声明:&lt;br /&gt;
&lt;br /&gt;
:* TLS协商需要在提供SASL之前发生(即, TLS是必需的并且接受方实体已经在接收到的这次连接尝试的初次的初始化流头中应答过了).&lt;br /&gt;
:* SASL协商不可能发生在一个 服务器-服务器 连接中(即, 初始化服务器未提供一个证书以进行验证并且因而接受方实体回滚到使用服务器回拨协议[[RFC6120#提示性备注|XEP‑0220]]进行弱身份验证).&lt;br /&gt;
:* SASL已经协商过了(即, 接受方实体在成功进行SASL协商之后应答一个以流重启的方式发送的初始化流头).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;mechanisms/&amp;gt;元素必须为接受方实体提供给初始化实体的每个验证机制包含一个&amp;lt;mechanism/&amp;gt;子元素. 大家知道, 在XML中的&amp;lt;mechanism/&amp;gt;元素的顺序表示来自接受方实体的SASL机制的优先顺序(它不一定是来自初始化实体的优先顺序).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
       &amp;lt;mechanism&amp;gt;EXTERNAL&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
       &amp;lt;mechanism&amp;gt;SCRAM-SHA-1-PLUS&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
       &amp;lt;mechanism&amp;gt;SCRAM-SHA-1&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
       &amp;lt;mechanism&amp;gt;PLAIN&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
     &amp;lt;/mechanisms&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====初始化====&lt;br /&gt;
&lt;br /&gt;
为了开始SASL协商, 初始化实体发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;auth/&amp;gt;元素并在'mechanism'属性包含一个适当的值, 从而开始使用特定的验证机制进行握手. 这个元素可以包含XML字符串数据(用SASL术语来说, 就是&amp;quot;初始化应答&amp;quot;)，如果这个机制支持或必须要它的话. 如果初始化实体需要发送一个长度为零的初始化应答, 它必须以单个等号字符(&amp;quot;=&amp;quot;)来传输这个应答, 这表示那个应答是当前的但是不包含数据.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&lt;br /&gt;
         mechanism='PLAIN'&amp;gt;AGp1bGlldAByMG0zMG15cjBtMzA=&amp;lt;/auth&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果初始化实体后来发送另一个&amp;lt;auth/&amp;gt;元素而正在进行的验证握手还没完成, 接收方实体必须丢弃正在进行的握手而必须为后来请求的SASL机制处理新的握手.&lt;br /&gt;
&lt;br /&gt;
====挑战-应答序列====&lt;br /&gt;
&lt;br /&gt;
如果必要, 接收方实体通过发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;challenge/&amp;gt;元素来挑战初始化实体; 这个元素可以包含XML字符串数据(它必须根据被初始化实体选择的SASL机制的定义来生成).&lt;br /&gt;
&lt;br /&gt;
初始化实体通过发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;response/&amp;gt;元素来应答这个挑战; 这个元素可以包含XML字符串数据(它必须根据被初始化实体选择的SASL机制的定义来生成).&lt;br /&gt;
&lt;br /&gt;
如果必要y, 接收方实体发送更多挑战而初始化实体发送更多应答.&lt;br /&gt;
&lt;br /&gt;
这一系列的 挑战/应答 对 一直持续直到发生以下三件事情之一:&lt;br /&gt;
&lt;br /&gt;
:* 初始化实体退出这个验证机制的握手.&lt;br /&gt;
:* 接收方实体报告握手失败.&lt;br /&gt;
:* 接收方实体报告握手成功.&lt;br /&gt;
&lt;br /&gt;
这些场景具体描述在接下来的章节.&lt;br /&gt;
&lt;br /&gt;
====放弃====&lt;br /&gt;
&lt;br /&gt;
初始化实体通过发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;abort/&amp;gt;元素放弃为这个验证机制所做的握手.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;abort xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在接收到一个&amp;lt;abort/&amp;gt;元素之后, 接收方实体必须返回一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;failure/&amp;gt;元素并在其中包含一个&amp;lt;aborted/&amp;gt;子元素.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;aborted/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====SASL失败====&lt;br /&gt;
&lt;br /&gt;
接收方实体通过发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;failure/&amp;gt;元素来汇报这个验证机制握手失败(特定的失败原因必须放进&amp;lt;failure/&amp;gt;元素的适当子元素，如 [[RFC6120#SASL定义|6.5]]定义的).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;not-authorized/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
为了选择适当的SASL机制, 接收方实体应该允许一个可配置的但是合理的重试次数(至少2次但不超过5次); 这让初始化实体能(例如, 一个终端用户客户端)容忍不正确的凭证(例如, 一个输错的密码)而不要强制重新连接(如果接收方实体立刻返回SASL失败并关闭流).&lt;br /&gt;
&lt;br /&gt;
如果初始化实体对同一个SASL机制尝试了合理的重试次数并且都失败了, 它可以回滚到顺序列表中的下一个机制，只要发送一个新的&amp;lt;auth/&amp;gt;请求给接收方实体, 从而开始那个机制的新的握手. 如果所有握手都失败了并且在初始化实体支持和可接受的机制列表里没有剩余的机制了, 初始化实体应该简单地关闭这个流，如[[RFC6120#关闭流|4.4]]所述(而不是等待这个流超时).&lt;br /&gt;
&lt;br /&gt;
如果初始化实体超出了重试次数, 接收方实体必须以一个流错误关闭流, 它应该是&amp;lt;policy-violation/&amp;gt;([[RFC6120#policy-violation|4.9.3.14]]), 不过一些现有的实现发送的是&amp;lt;not-authorized/&amp;gt;([[RFC6120#not-authorized|4.9.3.12]]).&lt;br /&gt;
&lt;br /&gt;
:实现备注: 对于 服务器-服务器 流, 如果接收方实体不能提供SASL EXTERNAL机制或其他基于TLS协商期间简历的安全上下文的SASL机制, 接收方实体可以尝试使用服务器回拨协议[[RFC6120#提示性备注|XEP‑0220]]来完成弱身份验证; 无论如何, 如果根据本地策略弱身份验证不足够的话，那么接收方实体应该以&amp;lt;policy-violation/&amp;gt;流错误([[RFC6120#policy-violation|4.9.3.14]])关闭这个流而不是等待这个流超时.&lt;br /&gt;
&lt;br /&gt;
====SASL成功====&lt;br /&gt;
&lt;br /&gt;
在确定SASL握手成功之前, 如果初始化实体在一个其保密和诚信得到TLS或同等的安全层(例如SASL GSSAPI机制)保护的初始化流头提供了一个'from'属性，那么接收方实体应该把这个验证身份结果关联到来自SASL协商的'from'地址; 如果这两个身份不匹配，那么接收方实体应该终止连接尝试(然而, 接收方实体可以有合法的理由不终止这个连接尝试, 例如, 因为它覆盖了一个连接的客户端的地址来纠正JID格式或根据终端用户的证书授予一个JID).&lt;br /&gt;
&lt;br /&gt;
接收方实体通过发送一个由'urn:ietf:params:xml:ns:xmpp-sasl'命名空间限定的&amp;lt;success/&amp;gt;元素来汇报握手成功; 这个元素可以包含XML字符串数据(在SASL 属于中, 是&amp;quot;成功的附加数据&amp;quot;), 如果选择的SASL机制支持或者要求它. 如果接收方实体需要发送零长度的附加数据, 它必须传送一个单独的等号字符(&amp;quot;=&amp;quot;)数据.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 对于 客户端-服务器 流, 在SASL协商时通讯的授权身份是用来根据接收方服务器为初始化客户端确定的权威地址, 如[[RFC6120#确定地址|4.3.6]]所述.&lt;br /&gt;
&lt;br /&gt;
一旦接收到&amp;lt;success/&amp;gt;元素, 初始化实体必须在现有的TCP连接上发送一个新的初始化流头到接收方实体来初始化一个新的流(如[[RFC6120#重启|4.3.3]]所述, 在发送新的初始化流头之前,初始化实体不能(MUST NOT)发送一个关闭&amp;lt;/stream&amp;gt;标签, 因为接收方实体和初始化实体必须确定原始的流被替换成SASL协商成功之后的流).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;stream:stream&lt;br /&gt;
     from='juliet@im.example.com'&lt;br /&gt;
     to='im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
一旦从初始化实体接收到新的初始化流头, 接收方实体必须发送一个新的流头给初始化实体来应答(为此它必须生成一个新的流ID而不是重用旧的流ID).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:stream&lt;br /&gt;
     from='im.example.com'&lt;br /&gt;
     id='gPybzaOzBmaADgxKXu9UClbprp0='&lt;br /&gt;
     to='juliet@im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
接收方实体也必须发送流特性, 包含任何更多的可用特性或不包含特性(通过一个空的&amp;lt;features/&amp;gt;元素).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
R: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SASL错误===&lt;br /&gt;
&lt;br /&gt;
SASL错误的语法如下, 那些用方括号 '[' 和 ']' 括起来的XML数据是可选的.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
  &amp;lt;defined-condition/&amp;gt;&lt;br /&gt;
  [&amp;lt;text xml:lang='langcode'&amp;gt;&lt;br /&gt;
      OPTIONAL descriptive text&lt;br /&gt;
  &amp;lt;/text&amp;gt;]&lt;br /&gt;
&amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;defined-condition&amp;quot; 必须是在接下来的章节里的定义的SASL相关的错误条件之一. 然而, 因为将来可能定义额外的错误条件, 如果一个实体收到一个它不理解的SASL错误条件，那么它必须把这个未知的条件视为一个通用的验证错误, 即, 等同于 &amp;lt;not-authorized/&amp;gt; ([[RFC6120#not-authorized|6.5.10]]).&lt;br /&gt;
&lt;br /&gt;
内含的&amp;lt;text/&amp;gt;元素是可选的, 并且可被用于提供关于这个错误条件的应用特有的信息, 这个信息可以显示给人看但只是作为已定义的条件的补充.&lt;br /&gt;
&lt;br /&gt;
因为XMPP本身定义了一个SASL应用范本并且不期望有更多专门的XMPP应用建立在SASL之上, 所以SASL错误格式不会像在XML流([[RFC6120#应用特有的条件|4.9.4]])和XML节([[RFC6120#应用特有条件|8.3.4]])的做法一样，为应用特有的错误提供扩展性.&lt;br /&gt;
&lt;br /&gt;
====aborted====&lt;br /&gt;
&lt;br /&gt;
接收方实体确认验证握手已经被初始化实体放弃; 对&amp;lt;abort/&amp;gt;元素发送应答.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;abort xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;aborted/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====account-disabled====&lt;br /&gt;
&lt;br /&gt;
初始化实体的帐号已经被暂时禁用; 对&amp;lt;auth/&amp;gt;元素或&amp;lt;response/&amp;gt;元素发送应答(可以包含或不包含初始化应答数据).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&lt;br /&gt;
         mechanism='PLAIN'&amp;gt;AGp1bGlldAByMG0zMG15cjBtMzA=&amp;lt;/auth&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;account-disabled/&amp;gt;&lt;br /&gt;
     &amp;lt;text xml:lang='en'&amp;gt;Call 212-555-1212 for assistance.&amp;lt;/text&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====credentials-expired====&lt;br /&gt;
&lt;br /&gt;
因为初始化实体提供的证书过期而验证失败; 对&amp;lt;response/&amp;gt;元素或&amp;lt;auth/&amp;gt;元素发送包含初始化应答数据的应答.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     [ ... ]&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;credentials-expired/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====encryption-required====&lt;br /&gt;
&lt;br /&gt;
初始化实体请求的机制不能使用，出非当前的流的保密性和完整性收到保护(典型的是通过TLS); 对&amp;lt;auth/&amp;gt;元素发送应答(包含或不包含初始化应答数据).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&lt;br /&gt;
         mechanism='PLAIN'&amp;gt;AGp1bGlldAByMG0zMG15cjBtMzA=&amp;lt;/auth&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;encryption-required/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====incorrect-encoding====&lt;br /&gt;
&lt;br /&gt;
初始化实体提供的数据无法被处理，因为 base 64 编码不正确(例如, 因为编码没有遵循[[RFC6120#常规备注|BASE64]]的第四章的定义); 对&amp;lt;response/&amp;gt;元素或&amp;lt;auth/&amp;gt;元素发送包含初始化应答数据的应答.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&lt;br /&gt;
         mechanism='DIGEST-MD5'&amp;gt;[ ... ]&amp;lt;/auth&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;incorrect-encoding/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====invalid-authzid====&lt;br /&gt;
&lt;br /&gt;
初始化实体提供的authzid是非法的, 要么因为它格式不正确要么因为初始化实体没有权限授权那个ID; 对&amp;lt;response/&amp;gt;元素或&amp;lt;auth/&amp;gt;元素发送包含初始化应答数据的应答.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     [ ... ]&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;invalid-authzid/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====invalid-mechanism====&lt;br /&gt;
&lt;br /&gt;
初始化实体没有指定一个机制, 或请求的机制不被接收方实体支持; 对&amp;lt;auth/&amp;gt;元素发送应答.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&lt;br /&gt;
         mechanism='CRAM-MD5'/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;invalid-mechanism/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====malformed-request====&lt;br /&gt;
&lt;br /&gt;
请求是不良的(例如, &amp;lt;auth/&amp;gt;元素包含了初始化应答数据但是机制不允许这个, 或被发送的数据违反了指定的SASL机制的语法); 对&amp;lt;abort/&amp;gt;, &amp;lt;auth/&amp;gt;, &amp;lt;challenge/&amp;gt;, 或 &amp;lt;response/&amp;gt; 元素发送应答.&lt;br /&gt;
&lt;br /&gt;
(下例中, &amp;lt;auth/&amp;gt;元素的XML字符串数据包含了多于255个UTF-8编码的Unicode字符，所以违反了定义于[[RFC6120#提示性备注|ANONYMOUS]]的SASL ANONYMOUS的&amp;quot;token&amp;quot;生产.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&lt;br /&gt;
         mechanism='ANONYMOUS'&amp;gt;[ ... some-long-token ... ]&amp;lt;/auth&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;malformed-request/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mechanism-too-weak====&lt;br /&gt;
&lt;br /&gt;
初始化实体请求的机制弱于服务器策略允许初始化实体使用的机制; 对&amp;lt;auth/&amp;gt;元素发送应答(包含或不包含初始化应答数据).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&lt;br /&gt;
         mechanism='PLAIN'&amp;gt;AGp1bGlldAByMG0zMG15cjBtMzA=&amp;lt;/auth&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;mechanism-too-weak/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====not-authorized====&lt;br /&gt;
&lt;br /&gt;
验证失败，因为初始化实体没有提供正确的证书, 或因为发生了一些普通的验证失败而接收方实体不希望泄露失败原因的特定信息; 对&amp;lt;response/&amp;gt;元素或&amp;lt;auth/&amp;gt;元素发送包含初始化应答数据的应答.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     [ ... ]&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;not-authorized/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:安全警告: 这个错误条件包含但不限于不正确的证书或不存在的用户名的情形. 为了组织目录获取攻击, 不正确的证书和不存在的用户名两者没有区别.&lt;br /&gt;
&lt;br /&gt;
====temporary-auth-failure====&lt;br /&gt;
&lt;br /&gt;
验证失败，因为接收方实体的临时性错误, 可以建议初始化实体晚点再试; 对&amp;lt;auth/&amp;gt;元素或&amp;lt;response/&amp;gt;元素发送应答.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
I: &amp;lt;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     [ ... ]&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;temporary-auth-failure/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===SASL定义===&lt;br /&gt;
&lt;br /&gt;
[[RFC6120#常规备注|SASL]]的范本需求里面要求使用中的协议定义必须提供以下信息.&lt;br /&gt;
&lt;br /&gt;
:服务名:&lt;br /&gt;
::&amp;quot;xmpp&amp;quot; &lt;br /&gt;
:初始化序列:&lt;br /&gt;
::在初始化实体提供一个打开的XML流头之后，接收方实体以同样的方式应答, 接收方实体提供一个可接受的验证方法的列表. 初始化实体从列表里选择一个方法并在放在&amp;lt;auth/&amp;gt;元素的'mechanism'属性的值里发送给接收方实体, 可选择包含一个初始化应答以避免多一个来回. &lt;br /&gt;
:交换序列:&lt;br /&gt;
::挑战和应答是通过从接收方实体发给初始化实体的&amp;lt;challenge/&amp;gt;元素和从初始化实体发送给接收方实体的&amp;lt;response/&amp;gt;元素. 接收方实体通过发送&amp;lt;failure/&amp;gt;元素来报告失败，通过发送&amp;lt;success/&amp;gt;元素来报告成功; 初始化实体通过发送&amp;lt;abort/&amp;gt;元素来放弃交换. 在成功协商之后, 双方确认原始的XML流被关闭而双方发送新的流头. &lt;br /&gt;
:安全层协商:&lt;br /&gt;
::安全层，对于接收方实体来说，发送完&amp;lt;success/&amp;gt;元素的'&amp;gt;'字符之后立刻生效, 对于初始化实体来说，在接收到&amp;lt;success/&amp;gt;元素的'&amp;gt;'字符之后立刻生效. 层的顺序是先 [[RFC6120#常规备注|TCP]], then [[RFC6120#常规备注|TLS]], then [[RFC6120#常规备注|SASL]], 然后 XMPP. &lt;br /&gt;
:授权身份的使用:&lt;br /&gt;
::授权身份在XMPP中可被用于指示客户端的非缺省的&amp;lt;localpart@domainpart&amp;gt;; 空字符串等于缺少授权身份.&lt;br /&gt;
&lt;br /&gt;
==资源绑定==&lt;br /&gt;
===原理===&lt;br /&gt;
&lt;br /&gt;
在客户端从一个服务器验证之后, 它必须绑定一个特定的资源到这个流，这样服务器才能正确地对客户端寻址. 就是说, 必须有一个XMPP资源关联到客户端的纯JID (&amp;lt;localpart@domainpart&amp;gt;), 所以在那个流上使用的地址是一个全JID，格式为&amp;lt;localpart@domainpart/resource&amp;gt; (包含资源部分). 这确保服务器可以向客户端相关的实体而不是服务器本身或客户端的帐号递送XML节和从客户端相关的实体而不是服务器本身或客户端的帐号接收XML节, 详见 [[RFC6120#服务器处理XML节的规则|第十章]].&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 在绑定资源之前，客户端可以和服务器本身或客户端帐号交换数据，因为全JID只在被这个客户端和服务器之间已协商好的流的上下文的外部寻址时需要用到, 但这不是常规做法.&lt;br /&gt;
&lt;br /&gt;
在客户端已经绑定了一个资源到该流之后, 它被视为一个 &amp;quot;已连接的资源&amp;quot;. 服务器应该允许一个实体同时维持多个已连接资源, 每个已连接的资源关联到一个唯一的XML流并且和其他已连接的资源的资源部分是不同的.&lt;br /&gt;
&lt;br /&gt;
:安全警告: 服务器应该允许一个XMPP服务的管理员限制已连接资源的数量，为了防止特定的拒绝服务攻击，详见[[RFC6120#拒绝服务|13.12]].&lt;br /&gt;
&lt;br /&gt;
如果, 在完成资源绑定步骤之前, 客户端尝试发送一个XML节给另一个不是服务器本身或客户端的帐号的实体, 服务器不能(MUST NOT)处理这个节而必须以&amp;lt;not-authorized/&amp;gt;流错误([[RFC6120#not-authorized|4.9.3.12]])关闭这个流.&lt;br /&gt;
&lt;br /&gt;
资源绑定扩展的XML命名空间是 'urn:ietf:params:xml:ns:xmpp-bind'.&lt;br /&gt;
&lt;br /&gt;
===支持===&lt;br /&gt;
&lt;br /&gt;
在XMPP客户端和服务器实现中，对于资源绑定的支持是必需的.&lt;br /&gt;
&lt;br /&gt;
===流协商规则===&lt;br /&gt;
====强制协商====&lt;br /&gt;
&lt;br /&gt;
流的双方必须确保资源绑定是强制协商的.&lt;br /&gt;
&lt;br /&gt;
====重启====&lt;br /&gt;
&lt;br /&gt;
在资源绑定之后, 双方不能(MUST NOT)重启该流.&lt;br /&gt;
&lt;br /&gt;
===声明支持===&lt;br /&gt;
&lt;br /&gt;
在SASL协商成功之后，服务器发送一个新的应答流头给客户端, 这时服务器必须在它展示给客户端的流特性中包含一个由'urn:ietf:params:xml:ns:xmpp-bind'命名空间限定的&amp;lt;bind/&amp;gt;元素.&lt;br /&gt;
&lt;br /&gt;
服务器不能(MUST NOT)包含资源绑定流特性，直到客户端验证之后, 通常就是SASL协商成功之后.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:stream&lt;br /&gt;
       from='im.example.com'&lt;br /&gt;
       id='gPybzaOzBmaADgxKXu9UClbprp0='&lt;br /&gt;
       to='juliet@im.example.com'&lt;br /&gt;
       version='1.0'&lt;br /&gt;
       xml:lang='en'&lt;br /&gt;
       xmlns='jabber:client'&lt;br /&gt;
       xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在得到资源绑定是强制协商的通知之后, 客户端必须绑定一个资源到流上，如下面章节所述.&lt;br /&gt;
&lt;br /&gt;
===资源标识符的生成===&lt;br /&gt;
&lt;br /&gt;
最低限度，资源部分在&amp;lt;localpart@domainpart&amp;gt;已连接的资源中必须是唯一的. 这个强制性策略是由服务器来负责的.&lt;br /&gt;
&lt;br /&gt;
:安全警告: 资源部分可能是关乎安全的. 例如, 如果一个恶意的实体猜测一个客户端的资源部分然后它能确定该客户端(也就是控制的主体)是在线还是离线, 所以导致如[[RFC6120#连击状态信息|13.10.2]]所述的联机状态泄漏. 为了防止那种可能性, 客户端可以要么 (1) 它自己生成一个随机的资源部分，要么(2) 请求服务器帮它生成一个资源部分. 一个确保资源部分随机性的方法是生成一个通用唯一标识符(UUID)，如 [[RFC6120#提示性备注|UUID]] 所述.&lt;br /&gt;
&lt;br /&gt;
===服务器生成的资源标识符===&lt;br /&gt;
&lt;br /&gt;
一个服务器必须能代替客户端生成XMPP资源部分. 由服务器生成的资源部分必须是随机的(参见 [[RFC6120#常规备注|RANDOM]]). &lt;br /&gt;
&lt;br /&gt;
====成功情形====&lt;br /&gt;
&lt;br /&gt;
客户端，通过发送一个类型为&amp;quot;set&amp;quot;并包含了一个由'urn:ietf:params:xml:ns:xmpp-bind'命名空间限定的空的&amp;lt;bind/&amp;gt;元素的IQ节(见[[RFC6120#IQ语义|8.2.3]])来请求一个服务器生成的资源部分.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;iq id='tn281v37' type='set'&amp;gt;&lt;br /&gt;
    &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
一旦服务器为该客户端生成了一个XMPP部分, 它必须返回一个类型为&amp;quot;result&amp;quot;的IQ节给该客户端, 这个节里面必须包含一个&amp;lt;jid/&amp;gt;元素来指定服务器决定的已连接资源的全JID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='tn281v37' type='result'&amp;gt;&lt;br /&gt;
    &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
      &amp;lt;jid&amp;gt;&lt;br /&gt;
        juliet@im.example.com/4db06f06-1ea4-11dc-aca3-000bcd821bfb&lt;br /&gt;
      &amp;lt;/jid&amp;gt;&lt;br /&gt;
    &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====错误情形====&lt;br /&gt;
&lt;br /&gt;
当一个客户端在资源绑定时请求服务器生成一个资源部分, 定义了以下节错误条件:&lt;br /&gt;
&lt;br /&gt;
:* 该帐号已经达到了被允许的并发资源连接数量限制.&lt;br /&gt;
:* 该客户端不被允许绑定一个资源到该流.&lt;br /&gt;
&lt;br /&gt;
自然的, 可能有这里没定义的错误条件发生, 如[[RFC6120#节错误|8.3]]所述. &lt;br /&gt;
&lt;br /&gt;
=====资源约束=====&lt;br /&gt;
&lt;br /&gt;
如果帐号已经达到被允许的并发连接资源数限制, 服务器必须返回一个&amp;lt;resource-constraint/&amp;gt;节错误([[RFC6120#resource-constraint|8.3.3.18]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='tn281v37' type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='wait'&amp;gt;&lt;br /&gt;
       &amp;lt;resource-constraint&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====不允许=====&lt;br /&gt;
&lt;br /&gt;
如果客户端不被允许绑定一个资源到该流, 服务器必须返回一个&amp;lt;not-allowed/&amp;gt;节错误([[RFC6120#not-allowed|8.3.3.10]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='tn281v37' type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;not-allowed&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===客户端提交的资源标识符===&lt;br /&gt;
&lt;br /&gt;
不同于请求服务器代替自己生成一个资源部分, 一个客户端可以尝试提交一个它自己生成的或受控制的用户已经提供的资源部分. &lt;br /&gt;
&lt;br /&gt;
====成功情形====&lt;br /&gt;
&lt;br /&gt;
客户端发送类型为&amp;quot;set&amp;quot;包含&amp;lt;bind/&amp;gt;元素以及拥有非空XML字符串数据的&amp;lt;resource/&amp;gt;子元素的IQ节，以请求它的服务器接受一个客户端提交的资源部分.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;iq id='wy2xa82b4' type='set'&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
       &amp;lt;resource&amp;gt;balcony&amp;lt;/resource&amp;gt;&lt;br /&gt;
     &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
该服务器应该接受这个客户端提交的资源部分. 它返回一个类型为&amp;quot;result&amp;quot;的IQ节给该客户端, 其中包含一个&amp;lt;jid/&amp;gt;子元素来为已连接的资源指定全JID并包含未修改的客户端提交的文本.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='wy2xa82b4' type='result'&amp;gt;&lt;br /&gt;
    &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
      &amp;lt;jid&amp;gt;juliet@im.example.com/balcony&amp;lt;/jid&amp;gt;&lt;br /&gt;
    &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
或者, 基于本地服务策略，该服务器可以拒绝客户端提交的资源部分并以服务器生成的资源部分覆盖它.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='wy2xa82b4' type='result'&amp;gt;&lt;br /&gt;
    &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
      &amp;lt;jid&amp;gt;&lt;br /&gt;
   juliet@im.example.com/balcony 4db06f06-1ea4-11dc-aca3-000bcd821bfb&lt;br /&gt;
      &amp;lt;/jid&amp;gt;&lt;br /&gt;
    &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====错误情形====&lt;br /&gt;
&lt;br /&gt;
当一个客户端在资源绑定期间尝试提交它自己的XMPP资源部分, 除了[[RFC6120#错误条件|7.6.2]]还定义了以下节错误条件:&lt;br /&gt;
&lt;br /&gt;
:* 所提供的资源部分无法被服务器处理.&lt;br /&gt;
:* 所提供的资源部分已经被使用.&lt;br /&gt;
&lt;br /&gt;
自然的, 有一些未在这里定义的错误条件可能发生, 如[[RFC6120#节错误|8.3]]所述. &lt;br /&gt;
&lt;br /&gt;
=====坏请求=====&lt;br /&gt;
&lt;br /&gt;
如果提供的资源部分无法被服务器处理(例如, 因为它长度为零或因为它违反了定义于[[RFC6120#常规备注|XMPP‑ADDR]]的资源部分的其他规则 ), 该服务器可能返回一个&amp;lt;bad-request/&amp;gt;节错误([[RFC6120#bad-request|8.3.3.1]])而不应该处理这个资源部分，这样就保持了一致性.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='wy2xa82b4' type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====冲突=====&lt;br /&gt;
&lt;br /&gt;
如果当前有一个已连接的客户端的会话被新连接的客户端请求了, 服务器必须做以下事情之一(该服务器做的这些事情之一对于实现或者本地服务策略是一个麻烦, 尽管下面提供了一些建议).&lt;br /&gt;
&lt;br /&gt;
:# 以一个服务器生成的资源部分覆盖新连接的客户端提供的资源部分. 这一行为是被提倡的, 因为对于客户端实现来说它简化了资源绑定过程.&lt;br /&gt;
:# 不允许新连接的客户端的资源绑定并保持当前已连接客户端的会话. 这一行为既不提倡也不反对, 尽管实际上它在RFC 3920中被隐性地提倡; 然而, 请注意对&amp;lt;conflict/&amp;gt;错误的处理并不总是被现有的客户端实现支持的, 它经常被当成一个验证错误并且当收到这个错误的时候丢弃缓存的凭证.&lt;br /&gt;
:# 中止当前已连接的客户端的会话并允许新连接的客户端的资源绑定尝试. 尽管这是早期XMPP服务器实现的传统行为, 现在不提倡这么做了，因为它可能导致两个客户端互相挂掉多方的无线循环; 无论如何, 注意这个行为在某些布署场景中可能是适当的，要么如果服务器知道当前已连接的客户端有一个死连接，要么有一个[[RFC6120#静默对端的处理|4.6]]所述的断裂的流.&lt;br /&gt;
&lt;br /&gt;
如果服务器遵循1号行为, 它返回一个类型为&amp;quot;result&amp;quot;的&amp;lt;iq/&amp;gt;节给新连接的客户端, 这里的&amp;lt;bind/&amp;gt;元素的&amp;lt;jid/&amp;gt;子元素包含XML字符串数据指定该客户端的全JID, 包含服务器生成的资源部分.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='wy2xa82b4' type='result'&amp;gt;&lt;br /&gt;
    &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
      &amp;lt;jid&amp;gt;&lt;br /&gt;
   juliet@im.example.com/balcony 4db06f06-1ea4-11dc-aca3-000bcd821bfb&lt;br /&gt;
      &amp;lt;/jid&amp;gt;&lt;br /&gt;
    &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果服务器遵循2号行为, 它发送一个&amp;lt;conflict/&amp;gt;节错误([[RFC6120#conflict|8.3.3.2]])应答新连接的客户端的资源绑定尝试但是保持这个XML流，这样新连接的客户端有机会去协商一个不冲突的资源部分(即, 新连接的客户端在做下一次绑定资源的尝试之前需要选择一个不同的资源部分).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='wy2xa82b4' type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果服务器遵循3号行为, 它返回一个&amp;lt;conflict/&amp;gt;流错误([[RFC6120#conflict|4.9.3.3]])给当前的已连接客户端(如[[RFC6120#conflict|4.9.3.3]]所述)并返回一个类型为&amp;quot;result&amp;quot;的IQ节(表示成功)新连接的应答资源绑定尝试.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='wy2xa82b4' type='result'&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
       &amp;lt;jid&amp;gt;&lt;br /&gt;
         juliet@im.example.com/balcony&lt;br /&gt;
       &amp;lt;/jid&amp;gt;&lt;br /&gt;
     &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====重试====&lt;br /&gt;
&lt;br /&gt;
如果客户端提交资源部分的时候发生了一个错误, 服务器应该允许可配置的但是合理的重试次数(至少5次且不高于10次); 这让客户端能够不需要被迫重新连接就可以纠正不正确提通的资源部分(例如, 坏的数据格式或重复的文本字符串).&lt;br /&gt;
&lt;br /&gt;
在客户端达到重试次数限制之后, 服务器必须以&amp;lt;policy-violation/&amp;gt;流错误([[RFC6120#policy-violation|4.9.3.14]])关闭这个流.&lt;br /&gt;
&lt;br /&gt;
==XML节==&lt;br /&gt;
&lt;br /&gt;
在一个客户端和一个服务器(或两个服务器)完成了流协商之后, 双方就可以发送XML节了. 对于'jabber:client'和'jabber:server'命名空间定义了三种XML节: &amp;lt;message/&amp;gt;, &amp;lt;presence/&amp;gt;, 和 &amp;lt;iq/&amp;gt;. 另外, 这些节类型有五种常见属性. 这些常见属性, 以及这三种节类型的基本语义, 定义于本协议; 更多即时消息和联机状态应用相关以及有关XMPP扩展协议的应用的XML节语法的详细信息在[[RFC6120#常规应用|XMPP‑IM]]里提供.&lt;br /&gt;
&lt;br /&gt;
XMPP客户端和服务器实现必须支持本协议所定义的XML节语法和语义.&lt;br /&gt;
&lt;br /&gt;
:安全警告: 服务器不能(MUST NOT)处理部分的节，也不能(MUST NOT)针对一个节的任何部分仍在传输时(在承认收到关闭标签之前)猜测其含义.&lt;br /&gt;
&lt;br /&gt;
===常见属性===&lt;br /&gt;
&lt;br /&gt;
以下五种属性常见于 message, presence, 和 IQ 节. &lt;br /&gt;
&lt;br /&gt;
====to====&lt;br /&gt;
&lt;br /&gt;
'to'属性指定该节期望的接收者的JID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;message to='romeo@example.net'&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Art thou not Romeo, and a Montague?&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于基于'to'地址的入站和出站XML节的服务器处理的信息, 参考[[RFC6120#处理XML节的服务器规则|第十章]]. &lt;br /&gt;
&lt;br /&gt;
=====客户端-服务器流=====&lt;br /&gt;
&lt;br /&gt;
以下规则适用于已连接客户端通过一个'jabber:client'命名空间限定的XML流发送给它的服务器的节中包含的'to'属性.&lt;br /&gt;
&lt;br /&gt;
:# 一个拥有特定接收者(例如, 一个会话伙伴, 一个远程服务, 该服务器本身, 甚至该用户的纯JID的另一个资源)的节必须拥有一个'to'属性，它的值是一个XMPP地址.&lt;br /&gt;
:# 一个从客户端发送到服务器的由该服务器直接处理的节(例如, [[RFC6120#常规备注|XMPP‑IM]]所述的好友列表处理或发送给服务器用来广播给其他实体的的联机状态信息)不能(MUST NOT)拥有'to'属性.&lt;br /&gt;
&lt;br /&gt;
以下规则适用于服务器通过一个'jabber:client'命名空间限定的XML流发送到已连接客户端的节中包含的'to'属性..&lt;br /&gt;
&lt;br /&gt;
:# 如果该服务器从另一个已连接客户端或从一个对端服务器接收到该节, 在递送该节给该客户端之前该服务器不能(MUST NOT)修改'to'地址.&lt;br /&gt;
:# 如果该服务器本身生成了这个节(例如, 对类型为&amp;quot;get&amp;quot;或&amp;quot;set&amp;quot;的IQ节的应答, 即使该节不包含一个'to'地址), 这个节可以包含一个'to'地址, 这个地址必须是该客户端的全JID, 如果这个节不包含'to'地址，那么该客户端必须把'to'地址视为等同于该客户端的全JID.&lt;br /&gt;
&lt;br /&gt;
:实现备注: 只递送节到客户端的全JID还是用户的纯JID,是服务器的责任; 就是说, 客户端不需要检查收到的节的'to'地址. 然而, 如果客户端不检查'to'地址，那么建议最好检查纯JID部分(不是全JID), 因为'to'地址可能是该用户的纯JID, 该客户端的当前全JID, 或甚至是一个不同资源的全JID(例如, 在[[RFC6120#提示性备注|XEP‑0160]]所述的的所谓&amp;quot;离线消息&amp;quot;的情况下).&lt;br /&gt;
&lt;br /&gt;
=====服务器-服务器流=====&lt;br /&gt;
&lt;br /&gt;
以下规则适用于一个'jabber:server'命名空间限定的XML流(即,服务器-服务器 流)的上下文中包含的'to'属性.&lt;br /&gt;
&lt;br /&gt;
:# 一个节必须拥有'to'属性，它的值是一个XMPP地址; 如果服务器接收到一个不满足这一限定的节, 它必须以一个&amp;lt;improper-addressing/&amp;gt;流错误([[RFC6120#improper-addressing|4.9.3.7]])来关闭这个流.&lt;br /&gt;
:# 包含在这个节的'to'属性中的JID的域部分必须和通过SASL协商(见[[RFC6120#SASL协商|第六章]])与之通讯的, 或服务器回拨(见[[RFC6120#提示性备注|XEP‑0220]]),或类似的接收方服务器(或其中任何有效的域名)的完全合法域名FQDN匹配; 如果服务器接收到的节不满足这个限定, 它必须以&amp;lt;host-unknown/&amp;gt;流错误([[RFC6120#host-unknown|4.9.3.6]])或&amp;lt;host-gone/&amp;gt;流错误([[RFC6120#host-gone|4.9.3.5]])来关闭该流.&lt;br /&gt;
&lt;br /&gt;
====from====&lt;br /&gt;
&lt;br /&gt;
'from'属性指定发送者的JID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;message from='juliet@im.example.com/balcony'&lt;br /&gt;
         to='romeo@example.net'&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Art thou not Romeo, and a Montague?&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====客户端-服务器流=====&lt;br /&gt;
&lt;br /&gt;
以下规则适用于被'jabber:client'命名空间限定的XML流(即, 客户端-服务器 流)上下文中的'from'属性.&lt;br /&gt;
&lt;br /&gt;
:# 当服务器从一个已连接客户端接收到一个XML节, 该服务器必须给这个节添加一个'from'属性或覆盖这个由客户端指定的'from'属性, 这里'from'属性的值必须是服务器针对生成这个节的已连接资源确定的全JID (&amp;lt;localpart@domainpart/resource&amp;gt;) (见[[RFC6120#确定地址|4.3.6]]), 或在和订阅相关的联机状态信息节(见[[RFC6120#提示性备注|XMPP‑IM]])的情况下则是纯JID (&amp;lt;localpart@domainpart&amp;gt;).&lt;br /&gt;
:# 当服务器为它自己生成一个从服务器本身发送给客户端的节的时候, 这个节必须包含一个'from'属性，它的值是服务器在流协商中同意的纯JID (即, &amp;lt;domainpart&amp;gt;)(例如, 基于初始化流头中的'to'属性).&lt;br /&gt;
:# 当服务器生成一个从该服务器递送到已连接客户端的帐号本身的节的时候(例如, 在服务器代表客户端提供的数据存储服务的上下文中), 该节要么 (a) 不包含'from'属性，要么 (b) 包含一个值为该帐号纯JID(&amp;lt;localpart@domainpart&amp;gt;)的'from'属性.&lt;br /&gt;
:# 服务器不能(MUST NOT)给客户端发送不包含'from'属性的节，如果该节不是由服务器代表它本身生成的(例如, 如果它是由另一个客户端或对端服务器生成的，而该服务器仅仅递送它到客户端或一些其他的实体); 所以, 当一个客户端接收到一个不包含'from'属性的节的时候, 它必须假定这个节是从该用户帐号所在服务器发出的.&lt;br /&gt;
&lt;br /&gt;
=====服务器-服务器流=====&lt;br /&gt;
&lt;br /&gt;
以下规则适用于一个'jabber:server'命名空间限定的XML流(即,服务器-服务器 流)的上下文中包含的'from'属性.&lt;br /&gt;
&lt;br /&gt;
:# 一个节必须拥有'from'属性，它的值是一个XMPP地址; 如果服务器接收到一个不满足这一限定的节, 它必须以一个&amp;lt;improper-addressing/&amp;gt;流错误([[RFC6120#improper-addressing|4.9.3.7]])来关闭这个流.&lt;br /&gt;
:# 包含在这个节的'from'属性中的JID的域部分必须和通过SASL协商(见[[RFC6120#SASL协商|第六章]])与之通讯的, 或服务器回拨(见[[RFC6120#提示性备注|XEP‑0220]]),或类似的发送方服务器(或其中任何有效的域名)的完全合法域名FQDN匹配; 如果服务器接收到的节不满足这个限定, 它必须以&amp;lt;invalid-from/&amp;gt;流错误([[RFC6120#invalid-from|4.9.3.9]])来关闭该流.&lt;br /&gt;
&lt;br /&gt;
强制执行这些规则有助于组织特定的如[[RFC6120#拒绝服务|13.12]]所述的拒绝服务攻击.&lt;br /&gt;
&lt;br /&gt;
====id====&lt;br /&gt;
&lt;br /&gt;
'id'属性是由发起方实体用来跟踪可能从其他实体(类似中间服务器或预期的接收者)收到的和它生成的节有关的任何应答或错误节.&lt;br /&gt;
&lt;br /&gt;
这个'id'属性仅在当前流保持唯一性还是全局保持唯一性，取决于发起方实体本身.&lt;br /&gt;
&lt;br /&gt;
对于&amp;lt;message/&amp;gt;和&amp;lt;presence/&amp;gt;节来说, 建议发起方实体包含一个'id'属性; 对于&amp;lt;iq/&amp;gt;节来说, 它是必需的.&lt;br /&gt;
&lt;br /&gt;
如果生成的节包含一个'id'属性，那么对于其相应的应答或错误节来说，也必须包含一个'id'属性, 这个'id'属性的值必须和生成的节的那个'id'属性值匹配.&lt;br /&gt;
&lt;br /&gt;
IQ节语义强加了额外的约束，参见[[RFC6120#IQ语义|8.2.3]].&lt;br /&gt;
&lt;br /&gt;
====type====&lt;br /&gt;
&lt;br /&gt;
'type'属性指定该消息,联机状态或IQ节的用途或上下文. 'type'属性的特定的允许值依赖于这个节是一个消息, 联机状态, 还是IQ节. 为消息和联机状态节定义的值用于即时消息和联机状态应用，所以定义于[[RFC6120#常规备注|XMPP‑IM]]中, 而为IQ节定义的值指定所有结构化请求-应答交换中的语义部分(无论载荷是什么), 所以它定义于[[RFC6120#IQ语义|8.2.3]]. 唯一通用于所有三种节的'type'值是&amp;quot;error&amp;quot;，定义于[[RFC6120#节错误|8.3]].&lt;br /&gt;
&lt;br /&gt;
====xml:lang====&lt;br /&gt;
&lt;br /&gt;
一个节应该拥有'xml:lang'属性(定义于的2.12节[[RFC6120#常规备注|XML]])，如果这个节包含了XML字符串数据打算展示给用户(如[[RFC6120#常规备注|CHARSETS]]所解释的, &amp;quot;可读国际化&amp;quot;). 'xml:lang'属性的值指定任何这类可读XML字符串数据的缺省语言.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;presence from='romeo@example.net/orchard' xml:lang='en'&amp;gt;&lt;br /&gt;
  &amp;lt;show&amp;gt;dnd&amp;lt;/show&amp;gt;&lt;br /&gt;
  &amp;lt;status&amp;gt;Wooing Juliet&amp;lt;/status&amp;gt;&lt;br /&gt;
&amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'xml:lang'属性的指可以被特定子元素的'xml:lang'属性覆写.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;presence from='romeo@example.net/orchard' xml:lang='en'&amp;gt;&lt;br /&gt;
  &amp;lt;show&amp;gt;dnd&amp;lt;/show&amp;gt;&lt;br /&gt;
  &amp;lt;status&amp;gt;Wooing Juliet&amp;lt;/status&amp;gt;&lt;br /&gt;
  &amp;lt;status xml:lang='cs'&amp;gt;Dvo&amp;amp;#x0159;&amp;amp;#x00ED;m se Julii&amp;lt;/status&amp;gt;&lt;br /&gt;
&amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果一个由客户端生成的出站节不拥有'xml:lang'属性, 该客户端的服务器应该添加一个'xml:lang'属性，其值为客户端的出站流所指定的值，如[[RFC6120#xml:lang|4.7.4]]所述.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence from='romeo@example.net/orchard'&amp;gt;&lt;br /&gt;
     &amp;lt;show&amp;gt;dnd&amp;lt;/show&amp;gt;&lt;br /&gt;
     &amp;lt;status&amp;gt;Wooing Juliet&amp;lt;/status&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;presence from='romeo@example.net/orchard'&lt;br /&gt;
             to='juliet@im.example.com'&lt;br /&gt;
             xml:lang='en'&amp;gt;&lt;br /&gt;
     &amp;lt;show&amp;gt;dnd&amp;lt;/show&amp;gt;&lt;br /&gt;
     &amp;lt;status&amp;gt;Wooing Juliet&amp;lt;/status&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果一个被客户端或服务器接收到的入站节不拥有'xml:lang'属性, 一个实现必须假定缺省语言是该实体的输入流所指定的值，如[[RFC6120#xml:lang|4.7.4]]所述.&lt;br /&gt;
&lt;br /&gt;
'xml:lang'属性的值必须遵循 NMTOKEN 数据类型(定义于[[RFC6120#常规备注|XML]]的2.3节) 并且必须遵循定义于[[RFC6120#常规备注|LANGTAGS]]的格式.&lt;br /&gt;
&lt;br /&gt;
服务器不能(MUST NOT)修改或删除它从其他实体收到的节的'xml:lang'属性.&lt;br /&gt;
&lt;br /&gt;
===基本语义===&lt;br /&gt;
====消息语义====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;message/&amp;gt;节是一个&amp;quot;推送&amp;quot;机制，这里一个实体推送信息到另一个实体, 类似发生在email系统里的通讯一样. 所有消息节将拥有'to'属性用来指定该消息期望的接收者 (见[[RFC6120#to|8.1.1]]和[[RFC6120#没有'to'地址|10.3]]), 除非消息是被一个已连接的客户端帐号的纯JID发送的. 接收到一个带有'to'地址的消息节之后, 服务器应该尝试路由或递送它到期望的接收者那里(见[[RFC6120#处理XML节的服务器规则|第十章]]里和XML节相关的通用路由和递送规则). &lt;br /&gt;
&lt;br /&gt;
====联机状态语义====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;presence/&amp;gt;节是一个特定的&amp;quot;广播&amp;quot;或&amp;quot;发布-订阅&amp;quot;机制, 这里多个实体接收关于他们订阅的一个实体的信息(在这个案例中, 是网络可用性信息). 通常, 发布客户端应该发送一个不带有'to'属性的联机状态节, 这种情况下该客户端连接的那个服务器将广播那个节给所有已订阅的实体. 然而, 发布客户端也可以发送一个带有'to'属性的联机状态节, 这种情况下该服务器将路由或递送那个节到期望的接收者. 尽管&amp;lt;presence/&amp;gt;节大部分情况下是由XMPP客户端使用, 它也可能被服务器, 附加服务, 以及任何其他类型呃XMPP实体使用. 参见[[RFC6120#处理XML节的服务器规则|第十章]]中和XML节相关的通用路由和递送规则, 以及[[RFC6120#常规备注|XMPP‑IM]]中联机状态应用的特定规则.&lt;br /&gt;
&lt;br /&gt;
====IQ语义====&lt;br /&gt;
&lt;br /&gt;
信息查询(Info/Query),或IQ, 是一个&amp;quot;请求-应答&amp;quot;机制, 类似某些情况下的超文本传输协议[[RFC6120#提示性备注|HTTP]]. IQ的语义允许一个实体对另一个实体做出一个请求, 并接收一个应答. 这个请求和应答的数据内容由schema或其他限定IQ元素的直接子元素的XML命名空间相关的结构化定义(见[[RFC6120#扩展内容|8.4]])来限定, 发出请求的实体使用'id'属性来跟踪交互过程. 所以, IQ交互沿用了结构化数据交换的常见模式，类似 get/result 或 set/result (尽管适当的时候对于某个请求会返回一个error):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
  请求实体                     应答实体&lt;br /&gt;
----------                  ----------&lt;br /&gt;
    |                            |&lt;br /&gt;
    | &amp;lt;iq id='1' type='get'&amp;gt;     |&lt;br /&gt;
    |   [ ... payload ... ]      |&lt;br /&gt;
    | &amp;lt;/iq&amp;gt;                      |&lt;br /&gt;
    | -------------------------&amp;gt; |&lt;br /&gt;
    |                            |&lt;br /&gt;
    | &amp;lt;iq id='1' type='result'&amp;gt;  |&lt;br /&gt;
    |   [ ... payload ... ]      |&lt;br /&gt;
    | &amp;lt;/iq&amp;gt;                      |&lt;br /&gt;
    | &amp;lt;------------------------- |&lt;br /&gt;
    |                            |&lt;br /&gt;
    | &amp;lt;iq id='2' type='set'&amp;gt;     |&lt;br /&gt;
    |   [ ... payload ... ]      |&lt;br /&gt;
    | &amp;lt;/iq&amp;gt;                      |&lt;br /&gt;
    | -------------------------&amp;gt; |&lt;br /&gt;
    |                            |&lt;br /&gt;
    | &amp;lt;iq id='2' type='error'&amp;gt;   |&lt;br /&gt;
    |   [ ... condition ... ]    |&lt;br /&gt;
    | &amp;lt;/iq&amp;gt;                      |&lt;br /&gt;
    | &amp;lt;------------------------- |&lt;br /&gt;
    |                            |&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt; '''图5: IQ节的语义''' &amp;lt;/div&amp;gt;&lt;br /&gt;
----&amp;lt;br/&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
为强制这些语义, 以下规则适用:&lt;br /&gt;
&lt;br /&gt;
:1. 'id'属性对于IQ节是必需的.&lt;br /&gt;
:2. 'type'属性对于IQ节是必需的. 这个值必须是以下之一; 如果不是, 接收者或中间路由器必须返回一个&amp;lt;bad-request/&amp;gt;节错误([[RFC6120#bad-request|8.3.3.1]]).&lt;br /&gt;
::* get -- 该节请求信息, 查询需要什么数据以完成更多操作, 等等.&lt;br /&gt;
::* set -- 该节为完成某个操作提供需要的数据, 设置新值, 取代旧值, 等等.&lt;br /&gt;
::* result -- 该节是对成功的get或set请求的应答.&lt;br /&gt;
::* error -- 该节报告关于处理或递送一个get或set请求时发生的错误(见[[RFC6120#节错误|8.3]]).&lt;br /&gt;
:3. 接收到类型为&amp;quot;get&amp;quot;或&amp;quot;set&amp;quot;的IQ请求的实体必须返回一个类型为&amp;quot;result&amp;quot;或&amp;quot;error&amp;quot;的IQ应答. 该应答必须保留请求中的'id'属性(或为空，如果生成的节没有包含'id'属性).&lt;br /&gt;
:4. 接收到类型为&amp;quot;result&amp;quot;或&amp;quot;error&amp;quot;节的实体不能(MUST NOT)发送更多的类型为&amp;quot;result&amp;quot;或&amp;quot;error&amp;quot;的IQ应答来应答; 然而, 请求实体可以发送另一个请求(例如, 一个类型为&amp;quot;set&amp;quot;的IQ对之前在get/result对中查询到的信息提供特定的信息).&lt;br /&gt;
:5. 类型为&amp;quot;get&amp;quot;或&amp;quot;set&amp;quot;的IQ节必须严格地包含一个子元素, 它定义特定请求的语义.&lt;br /&gt;
:6. 类型为&amp;quot;result&amp;quot;的IQ节必须包含零或一个子元素.&lt;br /&gt;
:7. 类型为&amp;quot;error&amp;quot;的IQ节可以包含相关的&amp;quot;get&amp;quot;或&amp;quot;set&amp;quot;子元素并且必须包含一个&amp;lt;error/&amp;gt;子元素; 详见[[RFC6120#节错误|8.3]].&lt;br /&gt;
&lt;br /&gt;
===节错误===&lt;br /&gt;
&lt;br /&gt;
节相关的错误处理的方式类似流错误[[RFC6120#流错误|流错误]], 但是不像流错误那样，节错误是可恢复的; 所以, 他们不会导致XML和当前TCP连接的中止. 反之, 发现错误条件的实体返回一个错误节, 它是一个这样的节:&lt;br /&gt;
&lt;br /&gt;
:* 是和触发这个错误的已生成的节同种类型(message, presence, 或 IQ)&lt;br /&gt;
:* 'type'属性值设为&amp;quot;error&amp;quot;&lt;br /&gt;
:* 通常是把已生成的节的'from'和'to'互换&lt;br /&gt;
:* 镜像触发这个错误的已生成的节的'id'属性(如果有的话)&lt;br /&gt;
:* 包含一个&amp;lt;error/&amp;gt;子元素以指明错误条件并且对发送者可以采取的补救措施提供一个暗示(然而, 不可能总是能够不补救这个错误)&lt;br /&gt;
&lt;br /&gt;
====规则====&lt;br /&gt;
&lt;br /&gt;
以下规则适用于节错误:&lt;br /&gt;
&lt;br /&gt;
:# 检测到和节相关的错误条件的接收或处理实体应该返回一个错误节(对于IQ节必须这么做).&lt;br /&gt;
:# 该错误节应该简单地把生成的节中的'from'和'to'地址互换, 除非这么做将会 (1) 导致信息泄漏(参见[RFC6120#信息泄露|13.10]])或其他违反安全, 或 (2) 强迫错误节的发送者在该错误节的'from'或'to'地址中包含一个异常的JID.&lt;br /&gt;
:# 如果生成的节是&amp;lt;message/&amp;gt;或&amp;lt;presence/&amp;gt;并且包含了'id'属性，那么该错误节必须也包含'id'属性. 如果生成的节是&amp;lt;iq/&amp;gt;，那么该错误节必须包含一个'id'属性. 在所有情况下, 'id'属性的值必须和生成节的相同(或者是空，如果生成的节没有包含'id'属性).&lt;br /&gt;
:# 错误节必须包含一个&amp;lt;error/&amp;gt;子元素.&lt;br /&gt;
:# 返回错误节的实体可以传递它的JID给生成节的发送者(例如, 为了诊断或跟踪的目的)，通过附加一个'by'属性到&amp;lt;error/&amp;gt;子元素.&lt;br /&gt;
:# 返回错误节的实体可以包含被发送的原始XML，这样发送者能够检查, 如果必要的话, 并在尝试重发之前纠正该XML(然而, 这只是出于礼貌，并且原实体不能(MUST NOT)依赖接收到的原始载荷). 自然地, 该实体不能(MUST NOT)包含原始数据，如果它不是格式良好的XML, 违反XMPP的XML限制(见[[RFC6120#XML限制|11.1]]), 或反而是有害的(例如, 超出大小限制).&lt;br /&gt;
:# 如果'type'属性值不是&amp;quot;error&amp;quot;(或如果没有'type'属性), 不能(MUST NOT)包含一个&amp;lt;error/&amp;gt;子元素.&lt;br /&gt;
:# 接收到错误节的实体不能(MUST NOT)以更多的错误节来应答这个节; 这有助于防止死循环.&lt;br /&gt;
&lt;br /&gt;
====语法====&lt;br /&gt;
&lt;br /&gt;
节相关的错误的语法如下, 这里展示的用方括号'['和']'括起来的XML数据是可选的, 'intended-recipient' 是原始节指定的地址的那个实体的JID, 'sender' 是原始实体的JID, 而 'error-generator' 是检测到错误的并方会错误节的那个实体.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;stanza-kind from='intended-recipient' to='sender' type='error'&amp;gt;&lt;br /&gt;
  [OPTIONAL to include sender XML here]&lt;br /&gt;
  &amp;lt;error [by='error-generator']&lt;br /&gt;
         type='error-type'&amp;gt;&lt;br /&gt;
    &amp;lt;defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
    [&amp;lt;text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'&lt;br /&gt;
           xml:lang='langcode'&amp;gt;&lt;br /&gt;
      OPTIONAL descriptive text&lt;br /&gt;
    &amp;lt;/text&amp;gt;]&lt;br /&gt;
    [OPTIONAL application-specific condition element]&lt;br /&gt;
  &amp;lt;/error&amp;gt;&lt;br /&gt;
&amp;lt;/stanza-kind&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;stanza-kind&amp;quot;必须是 message, presence, 或 iq 之一.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;error-type&amp;quot; 必须是以下之一:&lt;br /&gt;
&lt;br /&gt;
:* auth -- 在提供身份之后重试&lt;br /&gt;
:* cancel -- 不要重试 (该错误不能加以弥补)&lt;br /&gt;
:* continue -- 继续 (这个条件只是个警告)&lt;br /&gt;
:* modify -- 在修改发送的数据之后重试&lt;br /&gt;
:* wait -- 等待之后重试 (该错误是暂时的)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;defined-condition&amp;quot;必须符合[[RFC6120#已定义条件|8.3.3]]定义的节错误条件之一. 然而, 因为将来可能会发生额外的错误条件, 如果实体接受到一个它不理解的节错误条件，那么它必须把这个未知的条件当成&amp;lt;undefined-condition/&amp;gt; ([[RFC6120#undefined-condition|8.3.3.21]]). 如果一个XMPP协议扩展的设计者或一个XMPP实现的开发者需要未在本协议中定义的节错误条件的通讯, 他们可以定义应用特有的命名空间所限定的应用特有的错误条件元素来实现这个目标.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;error/&amp;gt;元素:&lt;br /&gt;
&lt;br /&gt;
:* 必须包含一个已定义的条件元素.&lt;br /&gt;
:* 可以包含一个包含XML字符串数据的&amp;lt;text/&amp;gt;子元素，用来描述错误的详细信息; 这个元素必须由'urn:ietf:params:xml:ns:xmpp-stanzas'命名空间来限定并且应该拥有'xml:lang'属性来指定该XML字符串数据的自然语言.&lt;br /&gt;
:* 可以包含一个用于应用特有的错误条件的子元素; 这个元素必须由一个应用特有的命名空间来限定，以定义该元素的语法和语义.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;text/&amp;gt;元素是可选的. 如果包含了它, 它仅被用于提供描述和诊断信息以补充说明已定义条件或应用特有的条件的含义. 它不能(MUST NOT)被应用程序当成编程信息来解释. 它不应该被用于向自然人用户展示错误消息, 但是可以被附加在该已定义条件元素(以及, 可选的, 应用特有的条件元素)的错误消息上展示.&lt;br /&gt;
&lt;br /&gt;
:互操作性备注: 定义于[[RFC3920]]的语法包含了一个遗留的'code'属性, 它的语义已经被已定义的条件元素取代; 关于已定义的条件元素和遗留的'code'属性值之间的对应关系，可以在[[RFC6120#提示性备注|XEP‑0086]]]找到.&lt;br /&gt;
&lt;br /&gt;
====已定义的条件====&lt;br /&gt;
&lt;br /&gt;
以下条件是已定义好用于节错误的.&lt;br /&gt;
&lt;br /&gt;
error-type 的值是被推荐用于每个已定义的条件通常预期的类型; 无论如何, 在某些情况下不同的类型可能更合适. &lt;br /&gt;
&lt;br /&gt;
=====bad-request=====&lt;br /&gt;
&lt;br /&gt;
发送者发送的节里包含的XML不符合适当的schema或不能被拥有(例如, IQ节的'type'属性包含一个不能识别的值, 或一个被已知的命名空间限定的元素但是违反了该元素的已定义的语法); 相关的错误类型应该是&amp;quot;modify&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;iq from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='zj3v142b'&lt;br /&gt;
       to='im.example.com'&lt;br /&gt;
       type='subscribe'&amp;gt;&lt;br /&gt;
     &amp;lt;ping xmlns='urn:xmpp:ping'/&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;iq from='im.example.com'&lt;br /&gt;
       id='zj3v142b'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====conflict=====&lt;br /&gt;
&lt;br /&gt;
访问未被授权，因为一个现存的资源使用了相同的名字或地址; 相关的错误类型应该是&amp;quot;cancel&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;iq id='wy2xa82b4' type='set'&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
       &amp;lt;resource&amp;gt;balcony&amp;lt;/resource&amp;gt;&lt;br /&gt;
     &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;iq id='wy2xa82b4' type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====feature-not-implemented=====&lt;br /&gt;
&lt;br /&gt;
出现在XML节里的特性没有被预定的接收方或中间服务器实现，所以该节无法被处理(例如, 该实体知道该命名空间但是不认识元素名); 相关的错误类型应该是&amp;quot;cancel&amp;quot; 或 &amp;quot;modify&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;iq from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='9u2bax16'&lt;br /&gt;
       to='pubsub.example.com'&lt;br /&gt;
       type='get'&amp;gt;&lt;br /&gt;
     &amp;lt;pubsub xmlns='http://jabber.org/protocol/pubsub'&amp;gt;&lt;br /&gt;
       &amp;lt;subscriptions/&amp;gt;&lt;br /&gt;
     &amp;lt;/pubsub&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;iq from='pubsub.example.com'&lt;br /&gt;
       id='9u2bax16'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;feature-not-implemented&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
       &amp;lt;unsupported&lt;br /&gt;
           xmlns='http://jabber.org/protocol/pubsub#errors'&lt;br /&gt;
           feature='retrieve-subscriptions'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====forbidden=====&lt;br /&gt;
&lt;br /&gt;
请求的实体没有必要的许可来执行一个只允许特定授权角色或个体来完成的动作(即, 它通常和授权而不是验证有关); 相关的错误类型应该是&amp;quot;auth&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence&lt;br /&gt;
       from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='characters@muc.example.com/JulieC'&amp;gt;&lt;br /&gt;
     &amp;lt;x xmlns='http://jabber.org/protocol/muc'/&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;presence&lt;br /&gt;
       from='characters@muc.example.com/JulieC'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='auth'&amp;gt;&lt;br /&gt;
       &amp;lt;forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====gone=====&lt;br /&gt;
&lt;br /&gt;
接收者或服务器无法再用这个地址联系到, 通常是永久意义上的(和&amp;lt;redirect/&amp;gt;错误条件相反, 它被用于临时的地址失败); 相关的错误类型应该是&amp;quot;cancel&amp;quot;并且该错误节应该包含一个新的地址(如果可用的话)作为&amp;lt;gone/&amp;gt;元素的XML字符串数据(它必须是一个实体可以联系的唯一资源标识符[[RFC6120#常规备注|URI]]或国际化资源标识符[[RFC6120#提示性备注|IRI]], 典型的是一个[[RFC6120#提示性备注|XMPP‑URI]]定义的XMPP IRI.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&lt;br /&gt;
       from='juliet@im.example.com/churchyard'&lt;br /&gt;
       id='sj2b371v'&lt;br /&gt;
       to='romeo@example.net'&lt;br /&gt;
       type='chat'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;Thy lips are warm.&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;message&lt;br /&gt;
       from='romeo@example.net'&lt;br /&gt;
       id='sj2b371v'&lt;br /&gt;
       to='juliet@im.example.com/churchyard'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error by='example.net'&lt;br /&gt;
            type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'&amp;gt;&lt;br /&gt;
         xmpp:romeo@afterlife.example.net&lt;br /&gt;
       &amp;lt;/gone&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====internal-server-error=====&lt;br /&gt;
&lt;br /&gt;
服务器发生了错误的配置或其他阻止它处理改节的内部错误; 相关的错误类型应该是&amp;quot;cancel&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence&lt;br /&gt;
       from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='characters@muc.example.com/JulieC'&amp;gt;&lt;br /&gt;
     &amp;lt;x xmlns='http://jabber.org/protocol/muc'/&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;presence&lt;br /&gt;
       from='characters@muc.example.com/JulieC'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;internal-server-error&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====item-not-found=====&lt;br /&gt;
&lt;br /&gt;
找不到请求的JID地址或条目; 相关的错误类型应该是&amp;quot;cancel&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence from='userfoo@example.com/bar'&lt;br /&gt;
             id='pwb2n78i'&lt;br /&gt;
             to='nosuchroom@conference.example.org/foo'/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;presence from='nosuchroom@conference.example.org/foo'&lt;br /&gt;
             id='pwb2n78i'&lt;br /&gt;
             to='userfoo@example.com/bar'&lt;br /&gt;
             type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:安全警告: 如果这样做将会提供预定的接收者的网络可用性信息给一个未被授权知道这些信息的实体(关于联机状态信息授权的更多细节讨论，参考[[RFC6120#常规备注|XMPP-IM]]联机状态订阅的讨论)，那么应用不能(MUST NOT)返回这个错误; 相反它应该返回一个&amp;lt;service-unavailable/&amp;gt;错误([[RFC6120#service-unavailable|8.3.3.19]]).&lt;br /&gt;
&lt;br /&gt;
=====jid-malformed=====&lt;br /&gt;
&lt;br /&gt;
发送的实体所提供(例如, 在资源绑定的时候)或与之通讯(例如, 一个节的'to'地址)的XMPP地址或其中一部分违反了[[RFC6120#常规备注|XMPP‑ADDR]]定义的规则; 相关的错误类型应该是&amp;quot;modify&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence&lt;br /&gt;
       from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='ch@r@cters@muc.example.com/JulieC'&amp;gt;&lt;br /&gt;
     &amp;lt;x xmlns='http://jabber.org/protocol/muc'/&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;presence&lt;br /&gt;
       from='ch@r@cters@muc.example.com/JulieC'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error by='muc.example.com'&lt;br /&gt;
            type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;jid-malformed&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:实现备注: 强制XMPP本地部分的格式主要是相关帐号或实体所在的服务的责任(例如, example.com 服务负责返回所有和格式 &amp;lt;localpart@example.com&amp;gt; 相关的 &amp;lt;jid-malformed/&amp;gt; 错误), 而强制XMPP域部分的格式主要是由路由一个节到域部分所指定的服务的那个服务的责任 (例如, example.org 服务负责返回该服务尝试发送的目标JID &amp;lt;localpart@example.com&amp;gt;的格式的 &amp;lt;jid-malformed/&amp;gt; 错误 ). 无论如何, 任何检测到格式错误的JID的实体可以返回该错误.&lt;br /&gt;
&lt;br /&gt;
=====not-acceptable=====&lt;br /&gt;
&lt;br /&gt;
接收者或服务器理解该请求但是不能处理它，因为该请求不符合该接收者或服务器的标准(例如, 请求订阅信息但是未同时包含接收者需要的配置参数); 相关的错误类型应该是&amp;quot;modify&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message to='juliet@im.example.com' id='yt2vs71m'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;[ ... the-emacs-manual ... ]&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;message from='juliet@im.example.com' id='yt2vs71m'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;not-acceptable&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====not-allowed=====&lt;br /&gt;
&lt;br /&gt;
接收者或服务器不允许任何实体执行该动作(例如, 向列入黑名单的域发送消息); 相关的错误类型应该是&amp;quot;cancel&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence&lt;br /&gt;
       from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='characters@muc.example.com/JulieC'&amp;gt;&lt;br /&gt;
     &amp;lt;x xmlns='http://jabber.org/protocol/muc'/&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;presence&lt;br /&gt;
       from='characters@muc.example.com/JulieC'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====not-authorized=====&lt;br /&gt;
&lt;br /&gt;
发送者在被允许执行某动作之前需要提供凭证, 或已经提供了错误的凭证(&amp;quot;not-authorized&amp;quot;的提法, 来源于[[RFC6120#提示性备注|HTTP]]的&amp;quot;401 Unauthorized&amp;quot;错误, 可能导致读者认为这个条件是和授权相关的, 但其实它通常用于验证相关的领域); 相关的错误类型应该是&amp;quot;auth&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence&lt;br /&gt;
       from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='characters@muc.example.com/JulieC'&amp;gt;&lt;br /&gt;
     &amp;lt;x xmlns='http://jabber.org/protocol/muc'/&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;presence&lt;br /&gt;
       from='characters@muc.example.com/JulieC'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='auth'&amp;gt;&lt;br /&gt;
       &amp;lt;not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====policy-violation=====&lt;br /&gt;
&lt;br /&gt;
实体违反了一些本地服务策略(例如, 一个消息包含了服务禁止的单词)而服务器可以选择在&amp;lt;text/&amp;gt;元素里或在应用特有的条件元素里指定策略; 相关的错误类型应该是&amp;quot;modify&amp;quot;或&amp;quot;wait&amp;quot;，取决于被违反的策略.&lt;br /&gt;
&lt;br /&gt;
(在下例中, 客户端发送一个包含了根据服务器的本地服务策略被禁止的单词的XMPP消息.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message from='romeo@example.net/foo'&lt;br /&gt;
            to='bill@im.example.com'&lt;br /&gt;
            id='vq71f4nb'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;%#&amp;amp;@^!!!&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;message from='bill@im.example.com'&lt;br /&gt;
            id='vq71f4nb'&lt;br /&gt;
            to='romeo@example.net/foo'&amp;gt;&lt;br /&gt;
     &amp;lt;error by='example.net' type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;policy-violation&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====recipient-unavailable=====&lt;br /&gt;
&lt;br /&gt;
预期的接收者暂时不可用, 正在维护, 等等; 相关的错误类型应该是&amp;quot;wait&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence&lt;br /&gt;
       from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='characters@muc.example.com/JulieC'&amp;gt;&lt;br /&gt;
     &amp;lt;x xmlns='http://jabber.org/protocol/muc'/&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;presence&lt;br /&gt;
       from='characters@muc.example.com/JulieC'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='wait'&amp;gt;&lt;br /&gt;
       &amp;lt;recipient-unavailable&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:安全警告: 如果这么做将提供关于预期接收者的网络可用性的信息给一个没有被授权可以知道这类信息的实体(对于联机状态授权方面的讨论的更多细节, 参考联机状态信息订阅的讨论[[RFC6120#常规备注|XMPP‑IM]]中),应用不能(MUST NOT)返回这个错误; 反之，它必须返回一个&amp;lt;service-unavailable/&amp;gt; 节错误([[RFC6120#service-unavailable|8.3.3.19]]).&lt;br /&gt;
&lt;br /&gt;
=====redirect=====&lt;br /&gt;
&lt;br /&gt;
接收者或服务器重定向该信息的请求到另一个实体, 典型的临时发生的情形(和&amp;lt;gone/&amp;gt;错误条件相反, 它用于永久性的地址错误); 相关的错误类型应该是&amp;quot;modify&amp;quot;，并且该错误节应该在&amp;lt;redirect/&amp;gt;元素的XML字符串数据中包含替代的地址(它必须是一个发送者可以与之通讯的URI或IRI, 通常是一个[[RFC6120#提示性备注|XMPP‑URI]]定义的XMPP IRI).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence&lt;br /&gt;
       from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='characters@muc.example.com/JulieC'&amp;gt;&lt;br /&gt;
     &amp;lt;x xmlns='http://jabber.org/protocol/muc'/&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;presence&lt;br /&gt;
       from='characters@muc.example.com/JulieC'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;redirect xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'&amp;gt;&lt;br /&gt;
         xmpp:characters@conference.example.org&lt;br /&gt;
       &amp;lt;/redirect&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:安全警告: 接收到一个节级别的重定向的应用应该向自然人用户警告这个重定向尝试并且在和包含在该&amp;lt;redirect/&amp;gt;元素的XML字符串数据中的地址代表的实体通讯之前请求批准, 因为那个实体可能有不同的身份或可能强制执行不同的安全策略. XMPP节的点对点验证或签名有助于减轻这个风险, 因为它将允许发送者来决定是否被重定向到的实体和开始尝试联系的实体是同一个身份. 应用可以有一个策略规定只有已经验证过接收实体才能重定向. 另外, 在成功地重定向了一定次数之后应用应该中止通讯尝试(例如, 至少2次但不超过5次).&lt;br /&gt;
&lt;br /&gt;
=====registration-required=====&lt;br /&gt;
&lt;br /&gt;
请求的实体没有被授权访问请求的服务，因为需要事先注册(提前注册的例子包括XMPP多用户聊天 [[XEP-0045]] 中仅限会员的房间和到非XMPP即时消息服务的网关, 传统上使用网关[[RFC6120#提示性备注|XEP‑0100]]是需要注册的); 相关的错误类型应该是&amp;quot;auth&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;presence&lt;br /&gt;
       from='juliet@im.example.com/balcony'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='characters@muc.example.com/JulieC'&amp;gt;&lt;br /&gt;
     &amp;lt;x xmlns='http://jabber.org/protocol/muc'/&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;presence&lt;br /&gt;
       from='characters@muc.example.com/JulieC'&lt;br /&gt;
       id='y2bs71v4'&lt;br /&gt;
       to='juliet@im.example.com/balcony'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='auth'&amp;gt;&lt;br /&gt;
       &amp;lt;registration-required&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====remote-server-not-found=====&lt;br /&gt;
&lt;br /&gt;
一个远程服务器或预期的接收者的JID的一部分所代表的服务不存在或不能解析(例如, 没有 _xmpp-server._tcp DNS SRV记录, A记录或AAAA记录解析也失败了, 或A/AAAA查询成功了但是在IANA注册了的端口5269上没有应答); 相关错误类型应该是&amp;quot;cancel&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&lt;br /&gt;
       from='romeo@example.net/home'&lt;br /&gt;
       id='ud7n1f4h'&lt;br /&gt;
       to='bar@example.org'&lt;br /&gt;
       type='chat'&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;yt?&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;message&lt;br /&gt;
       from='bar@example.org'&lt;br /&gt;
       id='ud7n1f4h'&lt;br /&gt;
       to='romeo@example.net/home'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;remote-server-not-found&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====remote-server-timeout=====&lt;br /&gt;
&lt;br /&gt;
远程服务器或作为预定的接收者的全JID的一部分(或履行请求所需要的)的服务能被解析但是无法在合理的时间内与之建立通讯(例如, 无法在解析到的IP地址和端口上建立一个XML流, 或可以建立一个XML流但是因为TLS, SASL, Server Dialback的问题导致流协商失败, 等等); 相关的错误类型应该是&amp;quot;wait&amp;quot; (除非该错误是更永久性的, 例如, 远程服务器能被找到但是无法被认证或它违反了安全策略).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&lt;br /&gt;
       from='romeo@example.net/home'&lt;br /&gt;
       id='ud7n1f4h'&lt;br /&gt;
       to='bar@example.org'&lt;br /&gt;
       type='chat'&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;yt?&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;message&lt;br /&gt;
       from='bar@example.org'&lt;br /&gt;
       id='ud7n1f4h'&lt;br /&gt;
       to='romeo@example.net/home'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='wait'&amp;gt;&lt;br /&gt;
       &amp;lt;remote-server-timeout&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====resource-constraint=====&lt;br /&gt;
&lt;br /&gt;
服务器或接收者忙或缺乏必要的系统资源来服务该请求; 相关的错误类型应该是&amp;quot;wait&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;iq from='romeo@example.net/foo'&lt;br /&gt;
       id='kj4vz31m'&lt;br /&gt;
       to='pubsub.example.com'&lt;br /&gt;
       type='get'&amp;gt;&lt;br /&gt;
     &amp;lt;pubsub xmlns='http://jabber.org/protocol/pubsub'&amp;gt;&lt;br /&gt;
       &amp;lt;items node='my_musings'/&amp;gt;&lt;br /&gt;
     &amp;lt;/pubsub&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;iq from='pubsub.example.com'&lt;br /&gt;
       id='kj4vz31m'&lt;br /&gt;
       to='romeo@example.net/foo'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='wait'&amp;gt;&lt;br /&gt;
       &amp;lt;resource-constraint&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====service-unavailable=====&lt;br /&gt;
&lt;br /&gt;
服务器或接收者当前未提供被请求的服务; 相关的错误类型应该是&amp;quot;cancel&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message from='romeo@example.net/foo'&lt;br /&gt;
            to='juliet@im.example.com'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;Hello?&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;message from='juliet@im.example.com/foo'&lt;br /&gt;
            to='romeo@example.net'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;service-unavailable&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:安全警告: 应用程序必须返回一个&amp;lt;service-unavailable/&amp;gt;节错误([[RFC6120#service-unavailable|8.3.3.19]])而不是&amp;lt;item-not-found/&amp;gt;([[RFC6120#item-not-found|8.3.3.7]])或&amp;lt;recipient-unavailable/&amp;gt;([[RFC6120#recipient-unavailable|8.3.3.13]]), 如果发送后面两个错误将提供关于预期的接收者的网络可用性信息给一个未被授权知道这写信息的实体(详见联机状态信息授权的讨论, 参考[[RFC6120#常规备注|XMPP‑IM]]).&lt;br /&gt;
&lt;br /&gt;
=====subscription-required=====&lt;br /&gt;
&lt;br /&gt;
提出请求的实体没有被授权访问所请求的服务，因为需要事先订阅(事先订阅的例子包括授权接收[[RFC6120#常规备注|XMPP‑IM]]定义的联机状态信息和用于[[RFC6120#提示性备注|XEP‑0060]]定义的XMPP发布-订阅的 opt-in 数据种子); 相关的错误类型应该是&amp;quot;auth&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&lt;br /&gt;
       from='romeo@example.net/orchard'&lt;br /&gt;
       id='pa73b4n7'&lt;br /&gt;
       to='playwright@shakespeare.example.com'&lt;br /&gt;
       type='chat'&amp;gt;&lt;br /&gt;
     &amp;lt;subject&amp;gt;ACT II, SCENE II&amp;lt;/subject&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;help, I forgot my lines!&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;message&lt;br /&gt;
       from='playwright@shakespeare.example.com'&lt;br /&gt;
       id='pa73b4n7'&lt;br /&gt;
       to='romeo@example.net/orchard'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='auth'&amp;gt;&lt;br /&gt;
       &amp;lt;subscription-required&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====undefined-condition=====&lt;br /&gt;
&lt;br /&gt;
该错误条件不在本列表中的其他错误条件之中; 任何错误类型都可能和本条件有关, 并且除非和应用特有的条件联合在一起，它应该不被使用.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message&lt;br /&gt;
       from='northumberland@shakespeare.example'&lt;br /&gt;
       id='richard2-4.1.247'&lt;br /&gt;
       to='kingrichard@royalty.england.example'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;My lord, dispatch; read o'er these articles.&amp;lt;/body&amp;gt;&lt;br /&gt;
     &amp;lt;amp xmlns='http://jabber.org/protocol/amp'&amp;gt;&lt;br /&gt;
       &amp;lt;rule action='notify'&lt;br /&gt;
             condition='deliver'&lt;br /&gt;
             value='stored'/&amp;gt;&lt;br /&gt;
     &amp;lt;/amp&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;message from='example.org'&lt;br /&gt;
            id='amp1'&lt;br /&gt;
            to='northumberland@example.net/field'&lt;br /&gt;
            type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;amp xmlns='http://jabber.org/protocol/amp'&lt;br /&gt;
          from='kingrichard@example.org'&lt;br /&gt;
          status='error'&lt;br /&gt;
          to='northumberland@example.net/field'&amp;gt;&lt;br /&gt;
       &amp;lt;rule action='error'&lt;br /&gt;
             condition='deliver'&lt;br /&gt;
             value='stored'/&amp;gt;&lt;br /&gt;
     &amp;lt;/amp&amp;gt;&lt;br /&gt;
     &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;undefined-condition&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
       &amp;lt;failed-rules xmlns='http://jabber.org/protocol/amp#errors'&amp;gt;&lt;br /&gt;
         &amp;lt;rule action='error'&lt;br /&gt;
               condition='deliver'&lt;br /&gt;
               value='stored'/&amp;gt;&lt;br /&gt;
       &amp;lt;/failed-rules&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====unexpected-request=====&lt;br /&gt;
&lt;br /&gt;
接收者或服务器理解这个请求但是不希望它在这个时候出现(即, 该请求顺序错了); 相关的错误类型应该是&amp;quot;wait&amp;quot;或&amp;quot;modify&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;iq from='romeo@example.net/foo'&lt;br /&gt;
       id='o6hsv25z'&lt;br /&gt;
       to='pubsub.example.com'&lt;br /&gt;
       type='set'&amp;gt;&lt;br /&gt;
     &amp;lt;pubsub xmlns='http://jabber.org/protocol/pubsub'&amp;gt;&lt;br /&gt;
        &amp;lt;unsubscribe&lt;br /&gt;
            node='my_musings'&lt;br /&gt;
            jid='romeo@example.net'/&amp;gt;&lt;br /&gt;
     &amp;lt;/pubsub&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&lt;br /&gt;
E: &amp;lt;iq from='pubsub.example.com'&lt;br /&gt;
       id='o6hsv25z'&lt;br /&gt;
       to='romeo@example.net/foo'&lt;br /&gt;
       type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
       &amp;lt;unexpected-request&lt;br /&gt;
           xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
       &amp;lt;not-subscribed&lt;br /&gt;
           xmlns='http://jabber.org/protocol/pubsub#errors'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====应用特有的条件====&lt;br /&gt;
&lt;br /&gt;
大家知道, 一个应用可以提供应用特有的节错误信息，通过在错误元素中包含一个正确的命名空间的子元素. 典型的, 该应用特有的元素补充或进一步限定一个已定义的元素. 从而, 该&amp;lt;error/&amp;gt;元素将包含两个或三个子元素.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iq id='ixc3v1b9' type='error'&amp;gt;&lt;br /&gt;
  &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
    &amp;lt;bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
    &amp;lt;too-many-parameters xmlns='http://example.org/ns'/&amp;gt;&lt;br /&gt;
  &amp;lt;/error&amp;gt;&lt;br /&gt;
&amp;lt;/iq&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;message type='error' id='7h3baci9'&amp;gt;&lt;br /&gt;
  &amp;lt;error type='modify'&amp;gt;&lt;br /&gt;
    &amp;lt;undefined-condition&lt;br /&gt;
          xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
    &amp;lt;text xml:lang='en'&lt;br /&gt;
          xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'&amp;gt;&lt;br /&gt;
      [ ... application-specific information ... ]&lt;br /&gt;
    &amp;lt;/text&amp;gt;&lt;br /&gt;
    &amp;lt;too-many-parameters xmlns='http://example.org/ns'/&amp;gt;&lt;br /&gt;
  &amp;lt;/error&amp;gt;&lt;br /&gt;
&amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
一个接收到它不理解的应用特有的错误条件的实体必须忽略那个条件但适当处理该错误节的其他部分.&lt;br /&gt;
&lt;br /&gt;
===扩展内容===&lt;br /&gt;
&lt;br /&gt;
尽管 message, presence, 和 IQ 节为消息,可用性,和 请求-应答 交互 提供了基本的语义, XMPP还使用XML命名空间 (见 [[RFC6120#常规备注|XML‑NAMES]]) 扩展基本的节语法来提供附加的功能.&lt;br /&gt;
&lt;br /&gt;
一个 message 或 presence 节可以包含一个或多个可选的子元素来指定扩展消息含义的内容(例如, [[RFC6120#提示性备注|XEP‑0071]]所述的的消息主体的XHTML格式版本), 并且一个类型为&amp;quot;get&amp;quot;或&amp;quot;set&amp;quot;的IQ节必须包含一个这样的子元素. 这样一个子元素可以使用任何名称并且必须拥有一个命名空间声明(不同于 &amp;quot;jabber:client&amp;quot;, &amp;quot;jabber:server&amp;quot;, 或 &amp;quot;http://etherx.jabber.org/streams&amp;quot;) 来定义子元素中的数据. 这样一个子元素被成为一个 &amp;quot;扩展元素&amp;quot;. 扩展元素可能被包含在节的直属子元素中，也可能包含在任何混合的层级里面. &lt;br /&gt;
&lt;br /&gt;
类似的, &amp;quot;扩展属性&amp;quot; 也是允许的. 表示说: 一个节本身 (即, 一个 &amp;lt;iq/&amp;gt;, &amp;lt;message/&amp;gt;, 或 &amp;lt;presence/&amp;gt; 元素，并由 &amp;quot;jabber:client&amp;quot; 或 &amp;quot;jabber:server&amp;quot; 内容命名空间限定) 或这样一个节的任何子元素 (一个由内容命名空间限定的扩展元素或子元素) 也可以包含一个或多个由不同于内容命名空间或保留的 &amp;quot;http://www.w3.org/XML/1998/namespace&amp;quot;  命名空间的其他命名空间(包括所谓 &amp;quot;空命名空间&amp;quot;，如果属性没有如[[RFC6120#常规备注|XML‑NAMES]]所说的那样做前缀的话)限定的属性. &lt;br /&gt;
&lt;br /&gt;
:互操作性备注: 为了向后兼容和最大化互操作性, 生成节的实体应该不在节本身或被内容命名空间&amp;quot;jabber:client&amp;quot; 或 &amp;quot;jabber:server&amp;quot; 限定的节的子元素(例如, &amp;lt;message/&amp;gt; 节的&amp;lt;body/&amp;gt; 子元素 )中包含这类属性. &lt;br /&gt;
&lt;br /&gt;
一个扩展元素或扩展属性被称为 &amp;quot;扩展内容&amp;quot; 并且限定这样一个元素或属性的命名空间被称为&amp;quot;扩展命名空间&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
:提示性备注: 尽管用于XMPP的扩展命名空间通常由XMPP标准化基金会(XSF)和IETF定义, 对于定义扩展命名空间来说，没有协议或IETF标准行为是必需的, 任何个体或组织都可以自由地定义XMPP扩展.&lt;br /&gt;
&lt;br /&gt;
为了说明这些概念, 下面有些例子.&lt;br /&gt;
&lt;br /&gt;
以下的节包含一个直接子元素，它的扩展命名空间是 'jabber:iq:roster': &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iq from='juliet@capulet.com/balcony'&lt;br /&gt;
    id='h83vxa4c'&lt;br /&gt;
    type='get'&amp;gt;&lt;br /&gt;
 &amp;lt;query xmlns='jabber:iq:roster'/&amp;gt;&lt;br /&gt;
&amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
以下节包含两个不同扩展命名空间的子元素.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;presence from='juliet@capulet.com/balcony'&amp;gt;&lt;br /&gt;
  &amp;lt;c xmlns='http://jabber.org/protocol/caps'&lt;br /&gt;
     hash='sha-1'&lt;br /&gt;
     node='http://code.google.com/p/exodus'&lt;br /&gt;
     ver='QgayPKawpkPSDYmwT/WM94uAlu0='/&amp;gt;&lt;br /&gt;
  &amp;lt;x xmlns='vcard-temp:x:update'&amp;gt;&lt;br /&gt;
    &amp;lt;photo&amp;gt;sha1-hash-of-image&amp;lt;/photo&amp;gt;&lt;br /&gt;
  &amp;lt;/x&amp;gt;&lt;br /&gt;
&amp;lt;/presence&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
以下节包含两个子元素, 其中一个被 &amp;quot;jabber:client&amp;quot; 或 &amp;quot;jabber:server&amp;quot; 内容命名空间限定，另一个被一个扩展命名空间限定; 而该扩展元素包含了一个由另一个扩展命名空间限定的子元素.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;message to='juliet@capulet.com'&amp;gt;&lt;br /&gt;
  &amp;lt;body&amp;gt;Hello?&amp;lt;/body&amp;gt;&lt;br /&gt;
  &amp;lt;html xmlns='http://jabber.org/protocol/xhtml-im'&amp;gt;&lt;br /&gt;
    &amp;lt;body xmlns='http://www.w3.org/1999/xhtml'&amp;gt;&lt;br /&gt;
      &amp;lt;p style='font-weight:bold'&amp;gt;Hello?&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
  &amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
实现不为扩展命名空间限定的元素生成命名空间前缀在XMPP社区是常见的(在XML社区, 这个惯例有时被称为&amp;quot;免前缀标准化&amp;quot;). 无论如何, 如果一个实现生成了这类命名空间前缀那么它必须在该节本身或该节的一个子元素中包含该命名空间的声明, 而不是在流头声明(见 [[RFC6120#其它命名空间|4.8.4]]). &lt;br /&gt;
&lt;br /&gt;
路由实体(典型的是服务器)处理序列化XML节的时候应该尝试保持前缀, 但是接收实体不能(MUST NOT)依赖该前缀字符串来获取任何特定的值(对于'stream'前缀的许可, 如[[RFC6120#命名空间声明和前缀|4.8.5]]所述, 是这个规则的一个例外, 尽管它是用于流而不是节的).&lt;br /&gt;
&lt;br /&gt;
在任何实现的特定部分对任何给定的扩展命名空间的支持都是可选的. 如果一个实体不理解这样一个命名空间, 该实体的的预期行为依赖于该实体是 (1) 接收者 还是 (2) 一个路由或递送该节给接收者的服务器.&lt;br /&gt;
&lt;br /&gt;
如果一个接收者收到一个包含了不理解的元素或属性的节, 它不能(MUST NOT)尝试处理那个XML数据，而必须按以下方式处理. &lt;br /&gt;
&lt;br /&gt;
:*如果一个预定的接收者受到一个message节，它的唯一子元素由不理解的命名空间限定, 那么根据XMPP应用它必须要么忽略整个节要么返回一个节错误, 节错误应该是 &amp;lt;service-unavailable/&amp;gt; ([[RFC6120#service-unavailable|8.3.3.19]]).&lt;br /&gt;
&lt;br /&gt;
:*如果预定的接收者接收到一个presence节，它的唯一子元素由它不理解的命名空间限定, 那么它必须忽略该子元素，把它当成没有子元素的联机状态信息节.&lt;br /&gt;
&lt;br /&gt;
:*如果预定的接收者收到一个message或presence节，它包含的XML数据由它不理解的命名空间来限定, 那么它必须忽略节的由未知的命名空间限定的那部分.&lt;br /&gt;
&lt;br /&gt;
:*如果预定的接收者接收到一个类型为&amp;quot;get&amp;quot;或&amp;quot;set&amp;quot;的IQ节，它包含的一个子元素由它不理解的命名空间限定, 那么实体必须返回一个类型为&amp;quot;error&amp;quot;且错误条件为&amp;lt;service-unavailable/&amp;gt;的IQ节.&lt;br /&gt;
&lt;br /&gt;
如果一个服务器持有一个节，是用来递送到另一个实体的，并且这个节包含了一个该服务器不理解的子元素, 它必须不加修改地路由或递送该节到一个和本地账户关联的已连接客户端.&lt;br /&gt;
&lt;br /&gt;
==详细示例==&lt;br /&gt;
&lt;br /&gt;
本章的详细示例用来进一步说明本标准所定义的协议. &lt;br /&gt;
&lt;br /&gt;
===客户端-服务器示例===&lt;br /&gt;
&lt;br /&gt;
以下例子展示客户端和服务器协商XML流, 交换XML节, 和关闭已协商的流的XMPP数据流. 服务器是&amp;quot;im.example.com&amp;quot;, 该服务器要求使用TLS, 客户端验证使用SASL SCRAM-SHA-1机制，客户端帐号是&amp;lt;juliet@im.example.com&amp;gt;而密码是&amp;quot;r0m30myr0m30&amp;quot;, 并且客户端在这个流上提交了一个资源绑定请求. 我们假设在发送初始化流头之前, 客户端已经解析了_xmpp‑client._tcp.im.example.com的SRV记录并已经打开一个TCP连接到已解析的IP地址和声明的端口上. &lt;br /&gt;
&lt;br /&gt;
====TLS====&lt;br /&gt;
&lt;br /&gt;
第一步: 客户端初始化流到服务器:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;stream:stream&lt;br /&gt;
     from='juliet@im.example.com'&lt;br /&gt;
     to='im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第二步: 服务器发送一个应答流头给客户端来应答:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:stream&lt;br /&gt;
     from='im.example.com'&lt;br /&gt;
     id='t7AMCin9zjMNwQKDnplntZPIDEI='&lt;br /&gt;
     to='juliet@im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第三步: 服务器发送流特性给客户端(在这个点上只有STARTTLS扩展, 它是强制协商的):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'&amp;gt;&lt;br /&gt;
       &amp;lt;required/&amp;gt;&lt;br /&gt;
     &amp;lt;/starttls&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第四步: 客户端发送STARTTLS命令给服务器:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第五步: 服务器通知客户端允许继续:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第五步(替代): 服务器通知客户端STARTTLS协商失败, 关闭XML流, 并中止TCP连接(所以, 流协商处理以不成功而结束并且双方不再进入下一步):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第六步: 客户端和服务器尝试通过现有的TCP连接完成TLS协商(详见[[RFC6120#常规备注|TLS]]).&lt;br /&gt;
&lt;br /&gt;
第七步: 如果TLS协商成功, 客户端通过TLS保护的TCP连接初始化一个新的流到服务器:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;stream:stream&lt;br /&gt;
     from='juliet@im.example.com'&lt;br /&gt;
     to='im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第七步(替代): 如果TLS协商不成功, 服务器关闭TCP连接(所以, 流协商处理以不成功而结束并且双方不再进入下一步): &lt;br /&gt;
&lt;br /&gt;
====SASL====&lt;br /&gt;
&lt;br /&gt;
第八步: 服务器发送流头给客户端并带上任何可用的流特性来应答:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:stream&lt;br /&gt;
     from='im.example.com'&lt;br /&gt;
     id='vgKi/bkYME8OAj4rlXMkpucAqe4='&lt;br /&gt;
     to='juliet@im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
       &amp;lt;mechanism&amp;gt;SCRAM-SHA-1-PLUS&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
       &amp;lt;mechanism&amp;gt;SCRAM-SHA-1&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
       &amp;lt;mechanism&amp;gt;PLAIN&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
     &amp;lt;/mechanisms&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第九步: 客户端选择一个验证机制(在这个场景中, 是 SCRAM-SHA-1), 包含初始化应答数据:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;auth xmlns=&amp;quot;urn:ietf:params:xml:ns:xmpp-sasl&amp;quot;&lt;br /&gt;
         mechanism=&amp;quot;SCRAM-SHA-1&amp;quot;&amp;gt;&lt;br /&gt;
     biwsbj1qdWxpZXQscj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQQ==&lt;br /&gt;
   &amp;lt;/auth&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
解码之后的 base 64 数据是 &amp;quot;n,,n=juliet,r=oMsTAAwAAAAMAAAANP0TAAAAAABPU0AA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
第十步: 服务器发送挑战:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;challenge xmlns=&amp;quot;urn:ietf:params:xml:ns:xmpp-sasl&amp;quot;&amp;gt;&lt;br /&gt;
     cj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQWUxMjQ2OTViLTY5Y&lt;br /&gt;
     TktNGRlNi05YzMwLWI1MWIzODA4YzU5ZSxzPU5qaGtZVE0wTURndE5HWTBaaT&lt;br /&gt;
     AwTmpkbUxUa3hNbVV0TkRsbU5UTm1ORE5rTURNeixpPTQwOTY=&lt;br /&gt;
   &amp;lt;/challenge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
解码后的 base 64 数据是 &amp;quot;r=oMsTAAwAAAAMAAAANP0TAAAAAABPU0AAe124695b-69a9-4de6-9c30-b51b3808c59e,s=NjhkYTM0MDgtNGY0Zi00NjdmLTkxMmUtNDlmNTNmNDNkMDMz,i=4096&amp;quot; (实际数据中是没有换行的).&lt;br /&gt;
&lt;br /&gt;
第十一步: 客户端发送一个应答:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;response xmlns=&amp;quot;urn:ietf:params:xml:ns:xmpp-sasl&amp;quot;&amp;gt;&lt;br /&gt;
     Yz1iaXdzLHI9b01zVEFBd0FBQUFNQUFBQU5QMFRBQUFBQUFCUFUwQUFlMTI0N&lt;br /&gt;
     jk1Yi02OWE5LTRkZTYtOWMzMC1iNTFiMzgwOGM1OWUscD1VQTU3dE0vU3ZwQV&lt;br /&gt;
     RCa0gyRlhzMFdEWHZKWXc9&lt;br /&gt;
   &amp;lt;/response&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
解码后的 base 64 数据是 &amp;quot;c=biws,r=oMsTAAwAAAAMAAAANP0TAAAAAABPU0 AAe124695b-69a9-4de6-9c30-b51b3808c59e,p=UA57tM/ SvpATBkH2FXs0WDXvJYw=&amp;quot; (实际数据中是没有换行的).&lt;br /&gt;
&lt;br /&gt;
第十二步: 服务器通知客户端成功了, 并且包含了额外的数据:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     dj1wTk5ERlZFUXh1WHhDb1NFaVc4R0VaKzFSU289&lt;br /&gt;
   &amp;lt;/success&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
解码后的 base 64 数据是 &amp;quot;v=pNNDFVEQxuXxCoSEiW8GEZ+1RSo=&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
第十二步(替代): 服务器返回一个SASL错误给客户端(所以, 流协商处理以不成功结束并且双方不再进行下一步):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
     &amp;lt;not-authorized/&amp;gt;&lt;br /&gt;
   &amp;lt;/failure&amp;gt;&lt;br /&gt;
   &amp;lt;/stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第十三步: 客户端初始化一个新的流到服务器:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;stream:stream&lt;br /&gt;
     from='juliet@im.example.com'&lt;br /&gt;
     to='im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====资源绑定====&lt;br /&gt;
&lt;br /&gt;
第十四步: 服务器发送一个流头到客户端并带上支持的特性(在这个场景中, 是资源绑定)来应答:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;stream:stream&lt;br /&gt;
     from='im.example.com'&lt;br /&gt;
     id='gPybzaOzBmaADgxKXu9UClbprp0='&lt;br /&gt;
     to='juliet@im.example.com'&lt;br /&gt;
     version='1.0'&lt;br /&gt;
     xml:lang='en'&lt;br /&gt;
     xmlns='jabber:client'&lt;br /&gt;
     xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S: &amp;lt;stream:features&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/&amp;gt;&lt;br /&gt;
   &amp;lt;/stream:features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在被通知资源绑定是强制协商之后, 客户端需要绑定一个资源到流; 这里我们假定客户端提交了一个自然人可读的文本字符串.&lt;br /&gt;
&lt;br /&gt;
第十五步: 客户端绑定一个资源:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;iq id='yhc13a95' type='set'&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
       &amp;lt;resource&amp;gt;balcony&amp;lt;/resource&amp;gt;&lt;br /&gt;
     &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第十六步: 服务器接受提交的资源部分并通知客户端资源绑定成功:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='yhc13a95' type='result'&amp;gt;&lt;br /&gt;
     &amp;lt;bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'&amp;gt;&lt;br /&gt;
       &amp;lt;jid&amp;gt;&lt;br /&gt;
         juliet@im.example.com/balcony&lt;br /&gt;
       &amp;lt;/jid&amp;gt;&lt;br /&gt;
     &amp;lt;/bind&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第十六步(替代): 服务器返回错误给客户端(所以, 流协商处理以不成功结束并且双方不再进入下一步):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;iq id='yhc13a95' type='error'&amp;gt;&lt;br /&gt;
     &amp;lt;error type='cancel'&amp;gt;&lt;br /&gt;
       &amp;lt;conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&amp;gt;&lt;br /&gt;
     &amp;lt;/error&amp;gt;&lt;br /&gt;
   &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====节交换====&lt;br /&gt;
&lt;br /&gt;
现在客户端被允许通过协商好的流发送XML节了.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;message from='juliet@im.example.com/balcony'&lt;br /&gt;
            id='ju2ba41c'&lt;br /&gt;
            to='romeo@example.net'&lt;br /&gt;
            type='chat'&lt;br /&gt;
            xml:lang='en'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;Art thou not Romeo, and a Montague?&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果必要, 发送者的服务器和预定的接收者的服务器协商XML流(见[[RFC6120#服务器-服务器示例|9.2]]).&lt;br /&gt;
&lt;br /&gt;
预定的接收者应答, 并且消息被递送到客户端.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
E: &amp;lt;message from='romeo@example.net/orchard'&lt;br /&gt;
            id='ju2ba41c'&lt;br /&gt;
            to='juliet@im.example.com/balcony'&lt;br /&gt;
            type='chat'&lt;br /&gt;
            xml:lang='en'&amp;gt;&lt;br /&gt;
     &amp;lt;body&amp;gt;Neither, fair saint, if either thee dislike.&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
客户端随后可以通过这个流继续发送和接收不限数量的XML节.&lt;br /&gt;
&lt;br /&gt;
====关闭====&lt;br /&gt;
&lt;br /&gt;
不想发送更多的消息, 客户端关闭它到服务器的流,不在等待来自服务器的入站数据了.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
C: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
和[[RFC6120#关闭流|4.4]]一致, 服务器可能发送额外的数据给客户端然后才关闭到该客户端的流.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
客户端现在发送一个 TLS close_notify 警告, 从服务器接收到一个 close_notify 警告应答, 然后中止当前的TCP连接.&lt;br /&gt;
&lt;br /&gt;
===服务器-服务器示例===&lt;br /&gt;
&lt;br /&gt;
以下示例展示一个服务器和对端服务器协商XML流，交换XML节, 和关闭已协商的流的数据流. 初始化服务器(&amp;quot;Server1&amp;quot;)是im.example.com; 接收服务器(&amp;quot;Server2&amp;quot;)是example.net 并且要求使用TLS; im.example.com递交一个证书并通过SASL EXTERNAL机制验证. 假定在发送初始化流头之前, Server1已经解析了一个SRV记录_xmpp-server._tcp.example.net并且已经打开了一个TCP连接到已解析的IP地址的声明的端口上. 注意Server1怎样声明内容命名空间&amp;quot;jabber:server&amp;quot;作为缺省的命名空间并为流相关的元素使用前缀, 反之Server2使用免前缀标准. &lt;br /&gt;
&lt;br /&gt;
====TLS====&lt;br /&gt;
&lt;br /&gt;
第一步: Server1初始化流到Server2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S1: &amp;lt;stream:stream&lt;br /&gt;
      from='im.example.com'&lt;br /&gt;
      to='example.net'&lt;br /&gt;
      version='1.0'&lt;br /&gt;
      xmlns='jabber:server'&lt;br /&gt;
      xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第二步: Server2发送一个应答流头到Server1来应答:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;stream&lt;br /&gt;
      from='example.net'&lt;br /&gt;
      id='hTiXkW+ih9k2SqdGkk/AZi0OJ/Q='&lt;br /&gt;
      to='im.example.com'&lt;br /&gt;
      version='1.0'&lt;br /&gt;
      xmlns='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第三步: Server2发送流特性给Server1(在这个点上只有STARTTLS扩展, 它是强制协商的):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;features xmlns='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
      &amp;lt;starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'&amp;gt;&lt;br /&gt;
        &amp;lt;required/&amp;gt;&lt;br /&gt;
      &amp;lt;/starttls&amp;gt;&lt;br /&gt;
    &amp;lt;/features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第四步: Server1发送STARTTLS指令给Server2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S1: &amp;lt;starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第五步: Server2通知Server1它被允许继续:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第五步(替代): Server2通知Server1 STARTTLS协商失败了, 关闭流, 并中止TCP连接(于是, 流协商过程以不成功结束并且双方不再进行下一步):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/&amp;gt;&lt;br /&gt;
    &amp;lt;/stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第六步: Server1和Server2尝试通过TCP完成TLS协商(详见[[RFC6120#常规备注|TLS]]).&lt;br /&gt;
&lt;br /&gt;
第七步: 如果TLS协商成功了, Server1在受TLS保护的TCP连接上初始化一个新流到Server2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S1: &amp;lt;stream:stream&lt;br /&gt;
      from='im.example.com'&lt;br /&gt;
      to='example.net'&lt;br /&gt;
      version='1.0'&lt;br /&gt;
      xmlns='jabber:server'&lt;br /&gt;
      xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第七步(替代): 如果TLS协商不成功, Server2关闭TCP连接(所以, 流协商过程以不成功结束并且双方不再进行下一步).&lt;br /&gt;
&lt;br /&gt;
====SASL====&lt;br /&gt;
&lt;br /&gt;
第八步: Server2发送一个应答流头给Server1并带上可用的流特性(包括优先的SASL EXTERNAL机制):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;stream&lt;br /&gt;
      from='example.net'&lt;br /&gt;
      id='RChdjlgj/TIBcbT9Keu31zDihH4='&lt;br /&gt;
      to='im.example.com'&lt;br /&gt;
      version='1.0'&lt;br /&gt;
      xmlns='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S2: &amp;lt;features xmlns='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
      &amp;lt;mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
        &amp;lt;mechanism&amp;gt;EXTERNAL&amp;lt;/mechanism&amp;gt;&lt;br /&gt;
      &amp;lt;/mechanisms&amp;gt;&lt;br /&gt;
    &amp;lt;/features&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第九步: Server1选择EXTERNAL机制(包含一个&amp;quot;=&amp;quot;的空应答):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S1: &amp;lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&lt;br /&gt;
          mechanism='EXTERNAL'&amp;gt;=&amp;lt;/auth&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第十步: Server2返回成功:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第十步(替代): Server2通知Server1验证失败了(所以, 流协商过程以不成功结束并且双方不再进行下一步):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&amp;gt;&lt;br /&gt;
      &amp;lt;not-authorized/&amp;gt;&lt;br /&gt;
    &amp;lt;/failure&amp;gt;&lt;br /&gt;
    &amp;lt;/stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第十一步: Server1初始化一个新流到Server2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S1: &amp;lt;stream:stream&lt;br /&gt;
      from='im.example.com'&lt;br /&gt;
      to='example.net'&lt;br /&gt;
      version='1.0'&lt;br /&gt;
      xmlns='jabber:server'&lt;br /&gt;
      xmlns:stream='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
第十二步: Server2发送一个流头给并带上任何附加的特性(或, 在这个例子中, 一个空的特性元素)来应答:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;stream&lt;br /&gt;
      from='example.net'&lt;br /&gt;
      id='MbbV2FeojySpUIP6J91qaa+TWHM='&lt;br /&gt;
      to='im.example.com'&lt;br /&gt;
      version='1.0'&lt;br /&gt;
      xmlns='http://etherx.jabber.org/streams'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
S2: &amp;lt;features xmlns='http://etherx.jabber.org/streams'/&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====节交换====&lt;br /&gt;
&lt;br /&gt;
现在Server1被允许通过已协商的从im.example.com到example.net的流发送XML节给Server2; 这里我们假定被传输的节就是前面演示的那些客户端-服务器通讯的节, 尽管是在一个服务器-服务器由'jabber:server'命名空间限定的流上.&lt;br /&gt;
&lt;br /&gt;
Server1发送XML节给Server2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S1: &amp;lt;message from='juliet@im.example.com/balcony'&lt;br /&gt;
             id='ju2ba41c'&lt;br /&gt;
             to='romeo@example.net'&lt;br /&gt;
             type='chat'&lt;br /&gt;
             xml:lang='en'&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;Art thou not Romeo, and a Montague?&amp;lt;/body&amp;gt;&lt;br /&gt;
   &amp;lt;/message&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====关闭====&lt;br /&gt;
&lt;br /&gt;
想不再发送更多消息, Server1关闭它到Server2的流但是等待从Server2的入站数据. (实践中, 流大部分时候保持打开一段时间, 因为Server1和Server2不是立刻知道流是否需要更多通讯.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S1: &amp;lt;/stream:stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
和建议的流关闭握手一致, Server2同样关闭流:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
S2: &amp;lt;/stream&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Server1现在发送一个TLS close_notify警告, 从Server2接收一个close_notify警告应答, 然后中止当前的TCP连接.&lt;br /&gt;
&lt;br /&gt;
==处理XML节的服务器规则==&lt;br /&gt;
&lt;br /&gt;
每个服务器实现将包含它自己的处理接受的节的逻辑. 这写逻辑决定服务器是需要路由一个给定的节到其他域, 还是把它递送到一个本地实体(典型的是一个和本地帐号相关联的已连接客户端), 或者直接由服务器本身处理它. 本章提供处理XML节的通用规则. 然而, 特殊的XMPP应用可以定义递送规则来修改或补充以下规则(例如, 定义于[[RFC6121|XMPP‑IM]]的用于即时消息和联机状态信息应用的一系列递送规则). &lt;br /&gt;
&lt;br /&gt;
===顺序处理===&lt;br /&gt;
&lt;br /&gt;
一个XMPP服务器必须确保它从一个已连接的客户端或远端服务器的给定的入站流上收到的节和其他XML元素的顺序处理.&lt;br /&gt;
&lt;br /&gt;
顺序处理适用于 (a) 任何用来协商和管理XML流的XML元素, 和 (b) 所有XML节, 包括但不限于以下情况:&lt;br /&gt;
&lt;br /&gt;
:#由一个客户端发送到它的服务器或它自己的纯JID的由服务器直接处理的节(例如, [[RFC6121|XMPP‑IM]]所述的获取好友名册和初始化出席信息的顺序处理).&lt;br /&gt;
:#由一个已连接的客户端发送的节并且是用来递送到另一个和该服务器相关的实体(例如, 从地址 &amp;lt;juliet@im.example.com&amp;gt; 发到 &amp;lt;nurse@im.example.com&amp;gt; 的节). 服务器必须确保按照从发送的客户端的入站流上接收到节的顺序来递送那些到预期接收者的节, 对递送目的接收者地址为纯JID和全JID的节等同对待.&lt;br /&gt;
:#由一个已连接的客户端发送的节并且是用来递送到一个位于远端服务器上的实体(例如, 从地址 &amp;lt;juliet@im.example.com&amp;gt; 发到 &amp;lt;romeo@example.net&amp;gt;). 路由的服务器必须确保按照从发送的客户端的入站流上接收到节的顺序来路由那些到预期接收者的节, 对路由目的接收者地址为纯JID和全JID的节等同对待. 为了帮助确保顺序处理, 路由服务器必须通过单一的到远端域的出站流来路由这些节, 而不是在一个服务器－服务器流上发送一些节而在另一个服务器－服务器流上发送另一些节.&lt;br /&gt;
:#从一个服务器路由到另一个服务器的递送到远端服务器的一个相关实体的节(例如, 从地址 &amp;lt;juliet@im.example.com&amp;gt; 发到 &amp;lt;romeo@example.net&amp;gt; 并且由 &amp;lt;im.example.com&amp;gt; 在一个服务器－服务器流上路由到 &amp;lt;example.net&amp;gt;). 递送服务器必须确保按照它从路由服务器的入站流上接收到的顺序来递送节, 对递送目的接收者地址为纯JID和全JID的节同等对待.&lt;br /&gt;
:#由一个服务器发送到另一个服务器用于远端域直接处理的节(例如, 从 &amp;lt;im.example.com&amp;gt; 发到 &amp;lt;example.net&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
如果服务器对于特定请求的处理对它接下来可能从入站流收到的数据的处理有影响(例如, 强制性的通讯策略), 它必须挂起接下来的数据的处理，直到它已经处理完该请求.&lt;br /&gt;
&lt;br /&gt;
顺序处理只适用于单一入站流. 所以, 服务器不负责保证它从相同本地帐号(例如, 通过两个不同入站流从&amp;lt;juliet@im.example.com/balcony&amp;gt; 和 &amp;lt;juliet@im.example.com/chamber&amp;gt;接收到的节) 或相同的远端域(例如, 由一个远端域通过两个不同的入站流进行的流协商; 然而, 服务器可以以&amp;lt;conflict/&amp;gt;流错误来关闭该流([[RFC6120#conflict|4.9.3.3]]),如果远端服务器尝试协商多个流, 详见[[RFC6120#conflict|4.9.3.3]])通过多个入站流接收到的数据的相干性.&lt;br /&gt;
&lt;br /&gt;
===一般注意事项===&lt;br /&gt;
===没有'to'地址===&lt;br /&gt;
====Message====&lt;br /&gt;
====Presence====&lt;br /&gt;
====IQ====&lt;br /&gt;
===远程域===&lt;br /&gt;
====现有流====&lt;br /&gt;
====无现有流====&lt;br /&gt;
====错误处理====&lt;br /&gt;
===本地域===&lt;br /&gt;
====域部分====&lt;br /&gt;
====域部分/资源部分====&lt;br /&gt;
&lt;br /&gt;
====本地部分@域部分====&lt;br /&gt;
=====没有此用户=====&lt;br /&gt;
=====用户存在=====&lt;br /&gt;
====本地部分@域部分/资源部分====&lt;/div&gt;</summary>
		<author><name>Terence lee100</name></author>	</entry>

	<entry>
		<id>http://wiki.jabbercn.org/Ejabberd2:%E5%AE%89%E8%A3%85%E5%92%8C%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97</id>
		<title>Ejabberd2:安装和操作指南</title>
		<link rel="alternate" type="text/html" href="http://wiki.jabbercn.org/Ejabberd2:%E5%AE%89%E8%A3%85%E5%92%8C%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97"/>
				<updated>2012-07-10T02:57:13Z</updated>
		
		<summary type="html">&lt;p&gt;Terence lee100: /* Local Router */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:XMPP服务器软件]]&lt;br /&gt;
[[Category:已翻译]]&lt;br /&gt;
&lt;br /&gt;
'''本文的英文原文来自 http://www.process-one.net/en/ejabberd/guide_en '''&lt;br /&gt;
&lt;br /&gt;
'''ejabberd 2.1.4 安装和管理指南'''&lt;br /&gt;
&lt;br /&gt;
==绪论==&lt;br /&gt;
&lt;br /&gt;
ejabberd是一个用[http://www.erlang.org/ Erlang/OTP]语言写的自由和开源的即时消息服务器.&lt;br /&gt;
&lt;br /&gt;
ejabberd是跨平台,分布式, 容错, 并基于开放标准的实时通讯系统.&lt;br /&gt;
&lt;br /&gt;
ejabberd的设计坚若磐石，是一个功能服丰富的XMPP服务器.&lt;br /&gt;
&lt;br /&gt;
ejabberd同时适合小规模布署和超大规模布署, 无论它们是否需要可伸缩性.&lt;br /&gt;
&lt;br /&gt;
===关键功能===&lt;br /&gt;
&lt;br /&gt;
ejabberd是:&lt;br /&gt;
&lt;br /&gt;
* 跨平台的: ejabberd可以运行在Microsoft Windows和Unix派生系统，例如Linux, FreeBSD和NetBSD.&lt;br /&gt;
* 分布式的: 你可以在一个集群的机器上运行ejabberd，并且所有的机器都服务于同一个或一些Jabbe域. 当你需要更大容量的时候，你可以简单地增加一个廉价节点到你的集群里. 因此, 你不需要买一个昂贵的高端机器来支持上万个并发用户.&lt;br /&gt;
* 容错: 你可以布署一个ejabberd集群，这样一个正常运行的服务的所有必需信息将被复制到所有节点. 这意味着如果其中一个节点崩溃了, 其他节点将无中断的继续运行. 另外, 也可以‘不停机’增加或更换节点.&lt;br /&gt;
* 易于管理: ejabberd建立于开源的Erlang. 所以你不需要安装外部服数据库, 外部web服务器, 除此以外因为每个东西都已经包含在里面, 并且处于开箱可用状态. 其他管理上的好处包括:&lt;br /&gt;
** 详尽的文档.&lt;br /&gt;
** 便捷的安装程序，包括在Linux, Mac OS X, 以及Windows系统下.&lt;br /&gt;
** Web管理.&lt;br /&gt;
** 共享名册组.&lt;br /&gt;
** 命令行管理工具.&lt;br /&gt;
** 可外部集成的验证机制.&lt;br /&gt;
** 发送匿名消息的能力. &lt;br /&gt;
* 国际化: ejabberd领导国际化. 非常适合全球化. 相关功能包括:&lt;br /&gt;
** 翻译成25种语言.&lt;br /&gt;
** 支持[http://www.ietf.org/rfc/rfc3490.txt IDNA]. &lt;br /&gt;
* 开放标准: ejabberd是的一个完全支持XMPP标准的开源Jabber服务器.&lt;br /&gt;
** 完全兼容XMPP.&lt;br /&gt;
** 基于XML的协议.&lt;br /&gt;
** 支持的[http://www.ejabberd.im/protocols 协议]很多.&lt;br /&gt;
&lt;br /&gt;
===额外功能===&lt;br /&gt;
&lt;br /&gt;
而且, ejabberd广泛支持的其他先进特性:&lt;br /&gt;
&lt;br /&gt;
* 模块化&lt;br /&gt;
** 只装在你想要的模块.&lt;br /&gt;
** 在你自己的自定义模块扩展ejabberd. &lt;br /&gt;
* 安全性&lt;br /&gt;
** 支持c2s和s2s连接的SASL和STARTTLS.&lt;br /&gt;
** 支持s2s连接的STARTTLS和Dialback.&lt;br /&gt;
** 可通过HTTPS安全访问的Web管理. &lt;br /&gt;
* 数据库&lt;br /&gt;
** 快速布署的内部数据库(Mnesia).&lt;br /&gt;
** 原生的MySQL支持.&lt;br /&gt;
** 原生的PostgreSQL支持.&lt;br /&gt;
** 支持ODBC数据存储.&lt;br /&gt;
** 支持Microsoft SQL Server. &lt;br /&gt;
* 验证&lt;br /&gt;
** 内部验证.&lt;br /&gt;
** PAM, LDAP 和 ODBC.&lt;br /&gt;
** 外部验证脚本. &lt;br /&gt;
* 其他&lt;br /&gt;
** 支持虚拟主机.&lt;br /&gt;
** XML流压缩 ([http://xmpp.org/extensions/xep-0138.html XEP-0138]).&lt;br /&gt;
** 统计 ([http://xmpp.org/extensions/xep-0039.html XEP-0039]).&lt;br /&gt;
** 支持IPv6的c2s和s2s连接.&lt;br /&gt;
** 支持集群和HTML日志的[[XEP-0045|多用户聊天]]模块.&lt;br /&gt;
** 基于用户vCards的用户目录.&lt;br /&gt;
** 支持[http://xmpp.org/extensions/xep-0163.html 基于PubSub的个人事件]的[http://xmpp.org/extensions/xep-0060.html 发行-订阅]组件.&lt;br /&gt;
** 支持web客户端: [http://xmpp.org/extensions/xep-0025.html HTTP轮询]和[http://xmpp.org/extensions/xep-0206.html HTTP绑定(BOSH)]服务.&lt;br /&gt;
** IRC网关.&lt;br /&gt;
** 组件支持: 安装特定网关之后和外部网络的接口，如 AIM, ICQ 和 MSN.&lt;br /&gt;
&lt;br /&gt;
==安装Installing ejabberd==&lt;br /&gt;
===用ejabberd二进制安装包安装===&lt;br /&gt;
&lt;br /&gt;
最简单的安装ejabberd即时消息服务器的方法可能是使用ProcessOne发布的二进制安装包. 已发布的ejabberd版本的二进制安装包在 ProcessOne ejabberd 下载页可以找到: http://www.process-one.net/en/ejabberd/downloads&lt;br /&gt;
&lt;br /&gt;
安装包将布署和配置一个完整的不需要任何依赖的ejabberd服务器.&lt;br /&gt;
&lt;br /&gt;
在 *nix 系统里, 记住启动之前把二进制安装包文件的属性设置成可执行的. 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
chmod +x ejabberd-2.0.0_1-linux-x86-installer.bin&lt;br /&gt;
./ejabberd-2.0.0_1-linux-x86-installer.bin&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ejabberd可以任何时候手工启动, 或在系统启动时由操作系统自动启动.&lt;br /&gt;
&lt;br /&gt;
要手动启动和停止, 可使用安装包建立的桌面快捷方式. 如果机器没有图形系统, 使用在ejabberd安装目录下的 ’bin’ 目录脚本 ’start’ 和 ’stop’.&lt;br /&gt;
&lt;br /&gt;
Windows安装包把ejabberd安装成了系统服务, 同时有一个快捷方式可以启动一个调试控制台给有经验的管理员使用. 如果你想ejabberd在开机时自动启动, 进入Windows服务设置界面并把ejabberd设置成自动启动. 注意Windows服务还是一个开发中的特性, 例如它不能读取ejabberdctl.cfg文件.&lt;br /&gt;
&lt;br /&gt;
在一个 *nix 系统, 如果你想ejabberd在开机时启动成为一个服务, 从 ’bin’目录拷贝 ejabberd.init 到类似 /etc/init.d/ejabberd (取决于你的操作系统的把本). 新建一个系统用户 ejabberd; 它将用于启动该服务的脚本. 然后你可以以root身份调用 /etc/inid.d/ejabberd 来启动服务.&lt;br /&gt;
&lt;br /&gt;
如果ejabberd不能在Windows里正确地启动, 尝试用启动菜单或桌面的快捷方式启动它. 如果window显式错误14001, 解决方案是安装: &amp;quot;Microsoft Visual C++ 2005 SP1 Redistributable Package&amp;quot;. 你可以从 http://www.microsoft.com/ 下载它. 然后卸载并再次安装ejabberd.&lt;br /&gt;
&lt;br /&gt;
如果ejabberd不能正确启动并且生成一个崩溃的dump, 表示有严重问题. 在Windows下你可以尝试使用 bin/live.bat 脚本启动ejabberd, 或在其它操作系统执行命令 bin/ejabberdctl live . 用这个办法你可以看到Erlang提供的错误消息并且辨别出确切的问题.&lt;br /&gt;
&lt;br /&gt;
ejabberdctl管理脚本位于 bin 目录. 关于ejabberdctl和用于微调Erlang运行时系统的可配置选项，详见 [[Ejabberd2:安装和操作指南#ejabberdctl|4.1]] 章.&lt;br /&gt;
&lt;br /&gt;
===用操作系统特定的包安装ejabberd===&lt;br /&gt;
&lt;br /&gt;
一些操作系统提供了特定的适应系统体系结构和库的ejabberd包. 它经常也会检查依赖的包并执行基本的配置任务，类似新建初始管理帐号. 例如Debian和Gentoo. 更多信息请查找你的操作系统提供的资源.&lt;br /&gt;
&lt;br /&gt;
那些包经常新建一个脚本，类似 /etc/init.d/ejabberd，在开机时启动和停止 ejabberd 服务.&lt;br /&gt;
&lt;br /&gt;
===用CEAN安装ejabberd===&lt;br /&gt;
&lt;br /&gt;
[http://cean.process-one.net/ CEAN] (Comprehensive Erlang Archive Network) 是一个存放了很多Erlang程序二进制包的仓库，包括了ejabberd和它所有的依赖包. 这些二进制包可用于多种不同的系统结构, 所以对于二进制安装包和操作系统的ejabberd包来说，这是一个备选.&lt;br /&gt;
&lt;br /&gt;
根据你如何处理你的CEAN安装而定，你需要新建自己的 ejabberd 启动脚本. 缺省的ejabberdctl脚本位于 ejabberd 的 priv 目录并且用作一个示例.&lt;br /&gt;
&lt;br /&gt;
===从源码安装ejabberd===&lt;br /&gt;
&lt;br /&gt;
发布ejabberd稳定版的规范方式是源码包. 从源码编译ejabberd在 *nix 系统是非常容易的, 只要你的系统拥有所有的依赖包.&lt;br /&gt;
&lt;br /&gt;
====需求====&lt;br /&gt;
&lt;br /&gt;
为了在一个‘类Unix’ 操作系统编译ejabberd, 你需要:&lt;br /&gt;
&lt;br /&gt;
* GNU Make&lt;br /&gt;
* GCC&lt;br /&gt;
* Libexpat 1.95 或更高版本&lt;br /&gt;
* Erlang/OTP R10B-9 或更高版本. 推荐的版本是 R12B-5. 对 R13 的支持是实验性质的.&lt;br /&gt;
* OpenSSL 0.9.6 或更高版本, 用于 STARTTLS, SASL 和 SSL 加密. 可选的, 高度推荐.&lt;br /&gt;
* Zlib 1.2.3 或更高版本, 用于支持流压缩 ([http://xmpp.org/extensions/xep-0138.html XEP-0138]). 可选的.&lt;br /&gt;
* Erlang mysql library. 可选的. 用于支持 MySQL 验证或存储. 见 [[Ejabberd2:安装和操作指南#MySQL|3.2.1]] 节.&lt;br /&gt;
* Erlang pgsql library. 可选的. 用于支持 PostgreSQL 验证或存储. 见 [[Ejabberd2:安装和操作指南#PostgreSQL|3.2.3]] 节.&lt;br /&gt;
* PAM library. 可选的. 用于F 可插拔的验证模块 (PAM). 见 [[Ejabberd2:安装和操作指南#PAM验证|3.1.4]] 节.&lt;br /&gt;
* GNU Iconv 1.8 或更高版本, 用于 IRC 网关 (mod_irc). 可选的. 在系统里不需要 GNU Libc. 见 [[Ejabberd2:安装和操作指南#mod_irc|3.3.8]] 节.&lt;br /&gt;
* ImageMagick’s 转换程序. 可选的. 用于 CAPTCHA 挑战. 见 [[Ejabberd2:安装和操作指南#CAPTCHA|3.1.8]] 节.&lt;br /&gt;
* exmpp 0.9.2 或更高版本. 可选的. 用于以 [http://xmpp.org/extensions/xep-0227.html XEP-0227] XML文件格式导入/导出用户数据.&lt;br /&gt;
&lt;br /&gt;
====下载源码====&lt;br /&gt;
&lt;br /&gt;
ejabberd的发布版本在 ProcessOne ejabberd 下载页: http://www.process-one.net/en/ejabberd/downloads&lt;br /&gt;
&lt;br /&gt;
另外, 最新的开发源码可使用命令行从 Git 仓库获得:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone git://git.process-one.net/ejabberd/mainline.git ejabberd&lt;br /&gt;
cd ejabberd&lt;br /&gt;
git checkout -b 2.1.x origin/2.1.x&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====编译====&lt;br /&gt;
&lt;br /&gt;
编译ejabberd可执行以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
./configure&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
编译配置脚本允许很多选项. 要获得所有选项列表执行以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
./configure --help&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
一些你可能有兴趣修改的选项如下:&lt;br /&gt;
&lt;br /&gt;
'''--prefix=/'''&lt;br /&gt;
&lt;br /&gt;
指定运行make install命令时文件将要拷贝的路径.&lt;br /&gt;
&lt;br /&gt;
'''--enable-user[=USER]'''&lt;br /&gt;
&lt;br /&gt;
允许普通系统用户执行ejabberdctl脚本 (参见 [[Ejabberd2:安装和操作指南#ejabberd|4.1]] 节), 读取配置, 读写 spool 目录, 读写 log 目录. 这个帐号的用户和组必须在运行make install之前就存在于机器上. 这个帐号不需要一个暴露的 HOME 目录, 因为缺省将使用 /var/lib/ejabberd/ .&lt;br /&gt;
&lt;br /&gt;
'''--enable-pam'''&lt;br /&gt;
&lt;br /&gt;
允许PAM验证方法 (参见 [[Ejabberd2:安装和操作指南#PAM验证|3.1.4]] 节).&lt;br /&gt;
&lt;br /&gt;
'''--enable-odbc or --enable-mssql'''&lt;br /&gt;
&lt;br /&gt;
如果你想使用外部数据库则需要这个选项. 详见 [[Ejabberd2:安装和操作指南#数据库和LDAP配置|3.2]] 节.&lt;br /&gt;
&lt;br /&gt;
'''--enable-full-xml'''&lt;br /&gt;
&lt;br /&gt;
允许使用基于XML的优化. 例如它将使用 CDATA 来逃逸 XMPP 流中的字符串. 只有你确定你的XMPP客户端有一个全兼容的XML分析器才使用这个选项.&lt;br /&gt;
&lt;br /&gt;
'''--disable-transient-supervisors'''&lt;br /&gt;
&lt;br /&gt;
对临时进程禁止使用Erlang/OTP监督.&lt;br /&gt;
&lt;br /&gt;
====安装====&lt;br /&gt;
&lt;br /&gt;
安装ejabberd到目标目录, 执行以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
注意安装ejabberd的时候你可能需要系统管理员的权限.&lt;br /&gt;
&lt;br /&gt;
缺省的新建文件和目录如下:&lt;br /&gt;
&lt;br /&gt;
 '''/etc/ejabberd/'''&lt;br /&gt;
    配置文件目录:&lt;br /&gt;
    '''ejabberd.cfg'''&lt;br /&gt;
        ejabberd配置文件&lt;br /&gt;
    '''ejabberdctl.cfg'''&lt;br /&gt;
        管理脚本配置文件&lt;br /&gt;
    '''inetrc'''&lt;br /&gt;
        网络DNS配置文件&lt;br /&gt;
&lt;br /&gt;
 '''/lib/ejabberd/'''&lt;br /&gt;
    '''ebin/'''&lt;br /&gt;
        Erlang二进制文件(*.beam) &lt;br /&gt;
    '''include/'''&lt;br /&gt;
        Erlang头文件(*.hrl) &lt;br /&gt;
    '''priv/'''&lt;br /&gt;
        运行时需要的其他文件&lt;br /&gt;
        '''bin/'''&lt;br /&gt;
            可执行程序&lt;br /&gt;
        '''lib/'''&lt;br /&gt;
            二进制系统文件(*.so) &lt;br /&gt;
        '''msgs/'''&lt;br /&gt;
            翻译文件(*.msgs) &lt;br /&gt;
&lt;br /&gt;
 '''/sbin/ejabberdctl'''&lt;br /&gt;
    管理脚本(见 [[Ejabberd2:安装和操作指南#ejabberdctl|4.1]] 节) &lt;br /&gt;
&lt;br /&gt;
 '''/share/doc/ejabberd/'''&lt;br /&gt;
    ejabberd文档&lt;br /&gt;
&lt;br /&gt;
 '''/var/lib/ejabberd/'''&lt;br /&gt;
    Spool目录:&lt;br /&gt;
    '''.erlang.cookie'''&lt;br /&gt;
        Erlang cookie文件(见 [[Ejabberd2:安装和操作指南# Erlang Cookie|5.3]] 节) &lt;br /&gt;
    '''acl.DCD, ...'''&lt;br /&gt;
        Mnesia数据库spool文件(*.DCD, *.DCL, *.DAT) &lt;br /&gt;
&lt;br /&gt;
 '''/var/log/ejabberd/'''&lt;br /&gt;
    日志目录(见 [[Ejabberd2:安装和操作指南#日志文件|7.1]] 节):&lt;br /&gt;
    '''ejabberd.log'''&lt;br /&gt;
        ejabberd服务日志&lt;br /&gt;
    '''erlang.log'''&lt;br /&gt;
        Erlang/OTP系统日志&lt;br /&gt;
&lt;br /&gt;
====启动====&lt;br /&gt;
&lt;br /&gt;
你可以使用ejabberdctl命令行管理脚本来启动和停止ejabberd. 如果你提供了配置选项 --enable-user=USER (见 [[Ejabberd2:安装和操作指南#编译|2.4.3]] 节), 你可以以那个系统帐号或root的身份执行ejabberdctl.&lt;br /&gt;
&lt;br /&gt;
用法示例:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ejabberdctl start&lt;br /&gt;
&lt;br /&gt;
ejabberdctl status&lt;br /&gt;
The node ejabberd@localhost is started with status: started&lt;br /&gt;
ejabberd is running in that node&lt;br /&gt;
&lt;br /&gt;
ejabberdctl stop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果ejabberd无法启动并生成一个崩溃dump, 表示有严重问题. 你可以尝试使用命令ejabberdctl live启动ejabberd来查看由Erlang提供的出错信息并识别出确切的问题.&lt;br /&gt;
&lt;br /&gt;
关于ejabberdctl和微调Erlang运行时系统的可配置选项，详见 [[Ejabberd2:安装和操作指南#ejabberdctl|4.1]] 节.&lt;br /&gt;
&lt;br /&gt;
如果你希望ejabberd在开机时以服务身份启动, 拷贝 ejabberd.init 到类似 /etc/init.d/ejabberd 目录(取决于你的操作系统版本). 新建一个系统用户ejabberd; 它将被启动该服务的脚本使用. 然后你可以以root身份在开机时调用 /etc/inid.d/ejabberd 来启动该服务.&lt;br /&gt;
&lt;br /&gt;
====BSD的具体说明====&lt;br /&gt;
&lt;br /&gt;
在BSD系统编译ejabberd的命令为:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
gmake&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Sun Solaris的具体说明====&lt;br /&gt;
&lt;br /&gt;
你需要一个GNU install, 但是Solaris里没有带. 如果你的Solaris系统是为 [http://www.blastwave.org/ blastwave.org] 包仓库配置的，这将很容易安装. 确保 /opt/csw/bin 目录在你的 PATH 参数里，然后运行:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pkg-get -i fileutils&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果那个软件名为 ginstall, 修改 ejabberd Makefile 脚本以适应你的系统, 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat Makefile | sed s/install/ginstall/ &amp;gt; Makefile.gi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
最终这样安装ejabberd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
gmake -f Makefile.gi ginstall&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Microsoft Windows的具体说明====&lt;br /&gt;
=====需求=====&lt;br /&gt;
&lt;br /&gt;
要在一个Microsoft Windows系统里编译ejabberd, 你需要:&lt;br /&gt;
&lt;br /&gt;
* MS Visual C++ 6.0 Compiler&lt;br /&gt;
* [http://www.erlang.org/download.html Erlang/OTP R11B-5]&lt;br /&gt;
* [http://sourceforge.net/project/showfiles.php?group_id=10127&amp;amp;package_id=11277 Expat 2.0.0或更高版本]&lt;br /&gt;
* [http://www.gnu.org/software/libiconv/ GNU Iconv 1.9.2 (可选的)]&lt;br /&gt;
* [http://www.slproweb.com/products/Win32OpenSSL.html Shining Light OpenSSL 0.9.8d或更高版本(使能SSL连接)]&lt;br /&gt;
* [http://www.zlib.net/ Zlib 1.2.3或更高版本]&lt;br /&gt;
&lt;br /&gt;
=====编译=====&lt;br /&gt;
&lt;br /&gt;
我们假定你将把很多库文件尽可能放在 C:\sdk\ 目录，这样更容易跟踪为了安装ejabberd都需要些什么.&lt;br /&gt;
&lt;br /&gt;
1. 安装 Erlang emulator (例如, 在 C:\sdk\erl5.5.5).&lt;br /&gt;
&lt;br /&gt;
2. 安装 Expat 库文件到 C:\sdk\Expat-2.0.0 目录.&lt;br /&gt;
&lt;br /&gt;
拷贝文件 C:\sdk\Expat-2.0.0\Libs\libexpat.dll 到你的Windows系统目录(例如, C:\WINNT 或 C:\WINNT\System32)&lt;br /&gt;
&lt;br /&gt;
3. 编译和安装 Iconv 库到目录 C:\sdk\GnuWin32.&lt;br /&gt;
&lt;br /&gt;
拷贝文件 C:\sdk\GnuWin32\bin\lib*.dll 到你的Windows系统目录(更多安装指引可在iconv分发版的 README.woe32 文件找到 ).&lt;br /&gt;
&lt;br /&gt;
注意: 也可以不拷贝 libexpat.dll 和 iconv.dll 到Windows系统目录, 而是把目录 C:\sdk\Expat-2.0.0\Libs 和 C:\sdk\GnuWin32\bin 加到 PATH 环境变量去.&lt;br /&gt;
&lt;br /&gt;
4. 安装 OpenSSL 到 C:\sdk\OpenSSL 目录并增加 C:\sdk\OpenSSL\lib\VC 到你的环境变量或拷贝二进制文件到你的系统目录.&lt;br /&gt;
&lt;br /&gt;
5. 安装 ZLib 到 C:\sdk\gnuWin32 目录. 拷贝 C:\sdk\GnuWin32\bin\zlib1.dll 到你的系统目录. 如果你修改了你的 path ，它应该在安装 libiconv 之后已经设置好了.&lt;br /&gt;
&lt;br /&gt;
6. 确保你能从你的路径访问Erlang二进制文件. 例如: set PATH=%PATH%;&amp;quot;C:\sdk\erl5.6.5\bin&amp;quot;&lt;br /&gt;
&lt;br /&gt;
7. 取决于你如果结束实际的库文件安装，你可能需要在文件configure.erl中检查和调整路径.&lt;br /&gt;
&lt;br /&gt;
8. 在目录ejabberd\src中运行:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      configure.bat&lt;br /&gt;
      nmake -f Makefile.win32&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
9. 编辑文件 ejabberd\src\ejabberd.cfg 并运行 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      werl -s ejabberd -name ejabberd&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===新建XMPP管理帐号===&lt;br /&gt;
&lt;br /&gt;
你需要一个XMPP帐号并赋予他管理权限来进行ejabberd Web管理:&lt;br /&gt;
&lt;br /&gt;
1. 在你的ejabberd服务器注册一个XMPP帐号, 例如admin1@example.org. 有两个办法来注册一个XMPP帐号:&lt;br /&gt;
&lt;br /&gt;
:1.1. 使用ejabberdctl (见 4.1 节):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
            ejabberdctl register admin1 example.org FgT5bk3&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:1.2. 使用一个XMPP客户端进行带内注册(见 3.3.18 节). &lt;br /&gt;
&lt;br /&gt;
2. 编辑ejabberd配置文件来给你创建的XMPP帐号赋予管理权限:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, admins, {user, &amp;quot;admin1&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {access, configure, [{allow, admins}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
你可以赋予管理权限给多个XMPP帐号, 也可以赋予权限给其他XMPP服务器.&lt;br /&gt;
&lt;br /&gt;
3. 重启ejabberd以装载新配置.&lt;br /&gt;
&lt;br /&gt;
4. 用你的浏览器打开Web管理界面(http://server:port/admin/). 确保键入了完整的JID作为用户名(在这个例子里是: admin1@example.org. 你需要加一个后缀的原因是因为ejabberd支持虚拟主机.&lt;br /&gt;
&lt;br /&gt;
===升级ejabberd===&lt;br /&gt;
&lt;br /&gt;
要升级一个ejabberd安装到一个新版本, 简单地卸载这个旧版本, 然后安装新版本就可以了. 当然, 重要的是配置文件和Mnesia数据库spool目录不能删除.&lt;br /&gt;
&lt;br /&gt;
在它需要的时候ejabberd在启动时会自动更新Mnesia数据表. 如果你也使用一个外部数据库来存储一些模块, 检查新的ejabberd版本的发布备注(release notes)是否指出也需要更新那些表.&lt;br /&gt;
&lt;br /&gt;
==配置ejabberd==&lt;br /&gt;
===基本配置===&lt;br /&gt;
&lt;br /&gt;
配置文件将在你第一次启动ejabberd时装载. 从该文件获得的内容将被解析并存储到内部的ejabberd数据库. 以后的配置将从数据库装载，并且任何配置文件里的命令都会被添加到数据库里.&lt;br /&gt;
&lt;br /&gt;
注意 ejabberd永远不编辑配置文件. 所以, 使用Web管理修改的配置被存储在数据库, 而不是反射到配置文件. 如果你想那些修改在ejabberd重启后还有效, 你可以同时也修改配置文件, 或删除它的所有内容.&lt;br /&gt;
&lt;br /&gt;
配置文件包含一系列Erlang条款. 以‘%’ 标志开始的行被忽略. 每个条款是一组元素，第一个元素是一个选项的名称, 任何更多的元素则是该选项的值. 如果配置文件不包含类似‘hosts’选项, 旧的存储在数据库的主机名(s)将被启用.&lt;br /&gt;
&lt;br /&gt;
你可以重写存储在数据库的值，通过在配置文件的开始部分增加下面几行:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
override_global.&lt;br /&gt;
override_local.&lt;br /&gt;
override_acls.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
有了这些行，旧的全局选项(在一个集群的所有ejabberd节点之间分享), 本地选项(特有的用于本地ejabberd节点的) 以及 ACLs 将在新配置添加之前被移除.&lt;br /&gt;
&lt;br /&gt;
====主机名====&lt;br /&gt;
&lt;br /&gt;
选项 hosts 定义了包含一个或多个ejabberd将为其提供服务的域名的列表.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{hosts, [HostName, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
示例:&lt;br /&gt;
&lt;br /&gt;
* 服务一个域:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {hosts, [&amp;quot;example.org&amp;quot;]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 服务多个域:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {hosts, [&amp;quot;example.net&amp;quot;, &amp;quot;example.com&amp;quot;, &amp;quot;jabber.somesite.org&amp;quot;]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====虚拟主机====&lt;br /&gt;
&lt;br /&gt;
每个虚拟主机的选项可以被独立定义，使用 host_config 选项.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{host_config, HostName, [Option, ...]}'''&lt;br /&gt;
&lt;br /&gt;
示例:&lt;br /&gt;
&lt;br /&gt;
* 域example.net使用内部验证方法，同时域example.com使用运行在域localhost的LDAP服务器来进行验证:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {host_config, &amp;quot;example.net&amp;quot;, [{auth_method,   internal}]}.&lt;br /&gt;
&lt;br /&gt;
      {host_config, &amp;quot;example.com&amp;quot;, [{auth_method,   ldap},&lt;br /&gt;
                                    {ldap_servers,  [&amp;quot;localhost&amp;quot;]},&lt;br /&gt;
                                    {ldap_uids,     [{&amp;quot;uid&amp;quot;}]},&lt;br /&gt;
                                    {ldap_rootdn,   &amp;quot;dc=localdomain&amp;quot;},&lt;br /&gt;
                                    {ldap_rootdn,   &amp;quot;dc=example,dc=com&amp;quot;},&lt;br /&gt;
                                    {ldap_password, &amp;quot;&amp;quot;}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 域example.net使用ODBC来进行验证，同时域example.com使用运行在域localhost和otherhost的LDAP服务器:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {host_config, &amp;quot;example.net&amp;quot;, [{auth_method, odbc},&lt;br /&gt;
                                    {odbc_server, &amp;quot;DSN=ejabberd;UID=ejabberd;PWD=ejabberd&amp;quot;}]}.&lt;br /&gt;
&lt;br /&gt;
      {host_config, &amp;quot;example.com&amp;quot;, [{auth_method,   ldap},&lt;br /&gt;
                                    {ldap_servers,  [&amp;quot;localhost&amp;quot;, &amp;quot;otherhost&amp;quot;]},&lt;br /&gt;
                                    {ldap_uids,     [{&amp;quot;uid&amp;quot;}]},&lt;br /&gt;
                                    {ldap_rootdn,   &amp;quot;dc=localdomain&amp;quot;},&lt;br /&gt;
                                    {ldap_rootdn,   &amp;quot;dc=example,dc=com&amp;quot;},&lt;br /&gt;
                                    {ldap_password, &amp;quot;&amp;quot;}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
为了给一个虚拟主机指定特定的ejabberd模块, 你可能先为常规模块定义全局模块选项, 之后增加指定的模块给特定的虚拟主机. 为此, 把定义host_config的每个选项改成通用语法&lt;br /&gt;
&lt;br /&gt;
'''{OptionName, OptionValue}'''&lt;br /&gt;
&lt;br /&gt;
使用这个语法:&lt;br /&gt;
&lt;br /&gt;
'''{{add, OptionName}, OptionValue}'''&lt;br /&gt;
&lt;br /&gt;
在这个例子里，三个虚拟主机有一些相同的模块, 但是特定的虚拟主机也有不同的模块:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
%% 这个ejabberd服务器有三个虚拟主机:&lt;br /&gt;
{hosts, [&amp;quot;one.example.org&amp;quot;, &amp;quot;two.example.org&amp;quot;, &amp;quot;three.example.org&amp;quot;]}.&lt;br /&gt;
&lt;br /&gt;
%% 这些是所有主机通用模块的配置&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  {mod_roster,     []},&lt;br /&gt;
  {mod_configure,  []},&lt;br /&gt;
  {mod_disco,      []},&lt;br /&gt;
  {mod_private,    []},&lt;br /&gt;
  {mod_time,       []},&lt;br /&gt;
  {mod_last,       []},&lt;br /&gt;
  {mod_version,    []}&lt;br /&gt;
 ]}.&lt;br /&gt;
&lt;br /&gt;
%% 增加一些模块给 vhost one:&lt;br /&gt;
{host_config, &amp;quot;one.example.org&amp;quot;,&lt;br /&gt;
 [{{add, modules}, [&lt;br /&gt;
                    {mod_echo,       [{host, &amp;quot;echo-service.one.example.org&amp;quot;}]}&lt;br /&gt;
                    {mod_http_bind,  []},&lt;br /&gt;
                    {mod_logxml,     []}&lt;br /&gt;
                   ]&lt;br /&gt;
  }&lt;br /&gt;
 ]}.&lt;br /&gt;
&lt;br /&gt;
%% 只增加一个模块给 vhost two:&lt;br /&gt;
{host_config, &amp;quot;two.example.org&amp;quot;,&lt;br /&gt;
 [{{add, modules}, [&lt;br /&gt;
                    {mod_echo,       [{host, &amp;quot;mirror.two.example.org&amp;quot;}]}&lt;br /&gt;
                   ]&lt;br /&gt;
  }&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====监听端口====&lt;br /&gt;
&lt;br /&gt;
选项 listen 定义ejabberd将监听哪些端口, 地址和网络协议，以及什么服务将运行在它们上面. 这个列表的每个元素是一组以下的元素:&lt;br /&gt;
&lt;br /&gt;
* 端口号. 还有可选的IP地址和/或一个传输协议.&lt;br /&gt;
* 监听这个端口的模块.&lt;br /&gt;
* TCP socke和监听中的模块的选项. &lt;br /&gt;
&lt;br /&gt;
这个选项的语法是:&lt;br /&gt;
&lt;br /&gt;
'''{listen, [Listener, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
定义一个 listener 有很多语法.&lt;br /&gt;
&lt;br /&gt;
'''{PortNumber, Module, [Option, ...]}'''&lt;br /&gt;
&lt;br /&gt;
'''{{PortNumber, IPaddress}, Module, [Option, ...]}'''&lt;br /&gt;
&lt;br /&gt;
'''{{PortNumber, TransportProtocol}, Module, [Option, ...]}'''&lt;br /&gt;
&lt;br /&gt;
'''{{PortNumber, IPaddress, TransportProtocol}, Module, [Option, ...]}'''&lt;br /&gt;
&lt;br /&gt;
=====端口号,IP地址和传输协议=====&lt;br /&gt;
&lt;br /&gt;
端口号定义哪个端口监听链入的连接. 它可能是一个Jabber/XMPP标准端口(见 [[Ejabberd2:安装和操作指南#防火墙设定|5.1]] 节) 或任何其他合法的端口号.&lt;br /&gt;
&lt;br /&gt;
IP地址可能被表达为一个字符串或一个十进制或十六进制的 Erlang 组. socket 将只监听那个网络接口. 也可能指定一个通用地址, 这样ejabberd将监听所有地址. 取决于IP地址的类型, 将使用IPv4或IPv6. 当没有指定IP地址时, 它将监听所有IPv4网络地址.&lt;br /&gt;
&lt;br /&gt;
一些IP地址的示例值:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;0.0.0.0&amp;quot; 监听所有IPv4网络接口. 这是当没有指定IP地址时的缺省值.&lt;br /&gt;
* &amp;quot;::&amp;quot; 监听所有IPv6网络接口&lt;br /&gt;
* &amp;quot;10.11.12.13&amp;quot; 监听IPv4地址 10.11.12.13&lt;br /&gt;
* &amp;quot;::FFFF:127.0.0.1&amp;quot; 是IPv6地址 ::FFFF:127.0.0.1/128&lt;br /&gt;
* {10, 11, 12, 13} 是IPv4地址 10.11.12.13&lt;br /&gt;
* {0, 0, 0, 0, 0, 65535, 32512, 1} 是IPv6地址 ::FFFF:127.0.0.1/128&lt;br /&gt;
* {16#fdca, 16#8ab6, 16#a243, 16#75ef, 0, 0, 0, 1} 是IPv6地址 FDCA:8AB6:A243:75EF::1/128 &lt;br /&gt;
&lt;br /&gt;
传输协议可能是 tcp 或 udp. 缺省是 tcp.&lt;br /&gt;
&lt;br /&gt;
=====监听的模块=====&lt;br /&gt;
&lt;br /&gt;
可用的模块, 它们的目的以及允许使用哪些选项:&lt;br /&gt;
&lt;br /&gt;
'''ejabberd_c2s'''&lt;br /&gt;
:处理c2s连接.&lt;br /&gt;
:选项: access, certfile, max_fsm_queue, max_stanza_size, shaper, starttls, starttls_required, tls, zlib &lt;br /&gt;
&lt;br /&gt;
'''ejabberd_s2s_in'''&lt;br /&gt;
:处理链入的s2s连接.&lt;br /&gt;
:选项: max_stanza_size &lt;br /&gt;
&lt;br /&gt;
'''ejabberd_service'''&lt;br /&gt;
:和一个[http://www.ejabberd.im/tutorials-transports 外部组件]的接口(定义于Jabber组件协议([http://xmpp.org/extensions/xep-0114.html XEP-0114]).&lt;br /&gt;
:选项: access, hosts, max_fsm_queue, shaper, service_check_from &lt;br /&gt;
&lt;br /&gt;
'''ejabberd_stun'''&lt;br /&gt;
:处理STUN绑定请求，定义于 [http://tools.ietf.org/html/rfc5389 RFC 5389].&lt;br /&gt;
:选项: certfile &lt;br /&gt;
&lt;br /&gt;
'''ejabberd_http'''&lt;br /&gt;
:处理链入的HTTP连接.&lt;br /&gt;
:选项: captcha, certfile, http_bind, http_poll, request_handlers, tls, web_admin&lt;br /&gt;
&lt;br /&gt;
=====选项=====&lt;br /&gt;
&lt;br /&gt;
这是每个监听的模块允许使用的选项的详细描述:&lt;br /&gt;
&lt;br /&gt;
'''{access, AccessName}'''&lt;br /&gt;
:这个选项定义访问的端口. 缺省值是 all. &lt;br /&gt;
'''{backlog, Value}'''&lt;br /&gt;
:这个backlog值定义等待中的连接的队列可以达到的最大长度. 如果服务器想处理很多的新链入连接，这个值需要增加。因为如果队列里没有足够的空间(ejabberd不能立刻接受它们)，这些新连接可能被抛弃. 缺省值是 5. &lt;br /&gt;
'''{certfile, Path}'''&lt;br /&gt;
:包含缺省的SSL证书的文件的完整路径. 为一个给定的域定义一个证书文件, 使用全局选项 domain_certfile. &lt;br /&gt;
'''{service_check_from, true|false}'''&lt;br /&gt;
:这个选项只能被用于ejabberd_service. 它被用于禁止控制一个从外部组件发送的包的from字段. 这个选项要么是 true 要么是 false. 缺省值是 true ，它遵循 [http://xmpp.org/extensions/xep-0114.html XEP-0114]. &lt;br /&gt;
'''{hosts, [Hostname, ...], [HostOption, ...]}'''&lt;br /&gt;
:连接到ejabberd_service的外部Jabber组件可能服务一个或多个hostnames. 所以你可以为这个组件定义选项 HostOption ; 目前只允许的选项是当组件尝试连接到ejabberd时必需提供的密码: {password, Secret}. 注意你不能在不同的服务里定义同一个 ejabberd_service 组件: 为每个服务增加一个 ejabberd_service , 示例如下. &lt;br /&gt;
'''captcha'''&lt;br /&gt;
:简单的web页面，允许一个用户填一个 CAPTCHA 挑战(见 [[Ejabberd2:安装和操作指南#CAPTCHA|3.1.8]] 节). &lt;br /&gt;
'''http_bind'''&lt;br /&gt;
:这个选项允许支持HTTP绑定([http://xmpp.org/extensions/xep-0124.html XEP-0124]和[http://xmpp.org/extensions/xep-0206.html XEP-0206]) . HTTP绑定允许通过HTTP请求，从那些不允许从5222端口链出socket的防火墙后面访问ejabberd.&lt;br /&gt;
:记住你也必须安装和激活mod_http_bind模块.&lt;br /&gt;
:如果HTTP绑定激活了, 它将可以使用 http://server:port/http-bind/. 注意对HTTP绑定的支持也需要XMPP客户端. 也要注意HTTP绑定对一个基于web的XMPP客户端的主机也是很有意义的，例如[http://jwchat.sourceforge.net/ JWChat] (检查教程来给ejabberd安装JWChat，以及一个 [http://www.ejabberd.im/jwchat-localserver 内嵌的本地web服务器] 或 [http://www.ejabberd.im/jwchat-apache Apache]). &lt;br /&gt;
'''http_poll'''&lt;br /&gt;
:这个选项允许支持HTTP轮询([http://xmpp.org/extensions/xep-0025.html XEP-0025]). HTTP轮询允许通过HTTP请求，从那些不允许从5222端口链出socket的防火墙后面访问ejabberd.&lt;br /&gt;
:如果激活了HTTP轮询, 它可以用 http://server:port/http-poll/. 注意对HTTP轮询的支持也需要XMPP客户端. 也要注意HTTP轮询对一个基于web的XMPP客户端的主机是很有意义的，例如[http://jwchat.sourceforge.net/ JWChat].&lt;br /&gt;
:在没有链入的POST请求时一个客户端会话保持激活状态的最大时间段，可以用全局选项 http_poll_timeout 配置. 缺省值为5分钟. 这个选项可在 ejabberd.cfg 文件里定义, 时间的单位为秒: {http_poll_timeout, 300}. &lt;br /&gt;
'''{max_fsm_queue, Size}'''&lt;br /&gt;
:这个选项指定在一个FSM(有限状态机)队列里元素的最大数量. 大概来说, 在这这些队列的每个消息展示一个准备发送到它想要的外发的流的XML节. 如果队列大小达到限制(因为, 例如, 节的接收者太慢), 这个FSM和相应的连接(如果有)将被终止并且记录一个出错信息. 这个选项的合理的值依赖于你的硬件配置. 无论如何, 把这个大小设为1000个元素以上应该没什么感觉. 这个选项可被指定给 ejabberd_service 和 ejabberd_c2s listeners, 或也可以全局地指定给 ejabberd_s2s_out. 如果这个选项没有指定给 ejabberd_service 或 ejabberd_c2s listeners, 则使用全局配置的值. 允许的值为整数和 ’undefined’. 缺省值为: ’undefined’. &lt;br /&gt;
'''{max_stanza_size, Size}'''&lt;br /&gt;
:这个选项指定一个XML节的近似最大字节数. 近似的, 是因为它计算的精度是以一个被读数据块来的. 例如 {max_stanza_size, 65536}. 缺省值是无穷大. 推荐的值对于c2s连接是 65536，对于s2s连接 是 131072 . s2s 最大节数必须总是比 c2s 的限制更高. 谨慎修改此值，因为如果设置得太小可能导致意料之外的断链. &lt;br /&gt;
'''{request_handlers, [ {Path, Module}, ...]}'''&lt;br /&gt;
:指定一个或多个 handlers 来伺服HTTP请求. Path是一个字符串列表; 所以以那个 Path 启动的 URIs 将被 Module 伺服. 例如, 你希望 mod_foo to 伺服以 /a/b/ 开头的URIs, 同时你也希望 mod_http_bind 伺服 URIs /http-bind/, 使用这个选项: {request_handlers, [{[&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;], mod_foo}, {[&amp;quot;http-bind&amp;quot;], mod_http_bind}]} &lt;br /&gt;
'''{service_check_from, true|false}'''&lt;br /&gt;
:通过使能这个选项, ejabberd 允许组件发送的包的’from’属性可以是任何随意的域. 注意 [http://xmpp.org/extensions/xep-0114.html XEP-0114] 要求域必须和组件的主机名吻合. 只有你确保自己需要的情况下才应该激活这个选项. 缺省值是: false. &lt;br /&gt;
'''{shaper, none|ShaperName}'''&lt;br /&gt;
:这个选项为端口定义一个塑型者 shaper (见 [[Ejabberd2:安装和操作指南#Shapers|3.1.6]] 节). 缺省值是 none. &lt;br /&gt;
'''starttls'''&lt;br /&gt;
:这个选项定义 STARTTLS 加密可以用于连接某端口. 你应该也设置 certfile 选项. 你可以使用全局选项 domain_certfile为一个特定的域定义一个证书文件. &lt;br /&gt;
'''starttls_required'''&lt;br /&gt;
:这个选项指定在连接到某端口时 STARTTLS 加密是必需的. 不允许不加密的连接. 你应该也设置 certfile 选项. 你可以使用全局选项 domain_certfile为一个特定的域定义一个证书文件. &lt;br /&gt;
'''tls'''&lt;br /&gt;
:这个选项指定某端口的通讯在连接之后将立刻使用SSL加密. 这是一个早期的Jabber软件使用的传统加密方法, 通常是在端口 5223 ，用于客户端－服务器通讯. 但是这个方法今天已经被藐视和不推荐了. 可取的加密方法是在端口5222使用 STARTTLS , 定义于 [[RFC3920|RFC 3920: XMPP核心]], 这个方法在 ejabberd 里可以使用 starttls 选项来激活. 如果这个选项被设置了, 你应该同时设置 certfile 选项. 选项 tls 也可用于 ejabberd_http 以支持 HTTPS. &lt;br /&gt;
'''web_admin'''&lt;br /&gt;
:这个选项激活为ejabberd管理激活 Web Admin ，可在 http://server:port/admin/ 访问. 登录和密码就是某个你在‘configure’ access rule里授权了的已注册用户的用户名和密码. &lt;br /&gt;
'''zlib'''&lt;br /&gt;
:这个选项指定在某端口的连接可使用 Zlib 流压缩(定义于 [http://xmpp.org/extensions/xep-0138.html XEP-0138]). &lt;br /&gt;
&lt;br /&gt;
有一些额外的全局选项(listen之外的)可以在ejabberd配置文件指定:&lt;br /&gt;
&lt;br /&gt;
'''{s2s_use_starttls, true|false}'''&lt;br /&gt;
:这个选项定义是否为s2s连接使用 STARTTLS . &lt;br /&gt;
'''{s2s_certfile, Path}'''&lt;br /&gt;
:一个包含SSL证书的文件的全路径. &lt;br /&gt;
'''{domain_certfile, Domain, Path}'''&lt;br /&gt;
:包含一个特定域的SSL证书的文件的全路径. &lt;br /&gt;
'''{outgoing_s2s_options, Methods, Timeout}'''&lt;br /&gt;
:指定用哪个地址尝试连接, 以什么顺序, 以及连接超时时间(以毫秒计). 缺省第一次尝试连接使用IPv4地址, 如果失败它将尝试使用IPv6, 超时时间为 10000 毫秒. &lt;br /&gt;
'''{s2s_dns_options, [ {Property, Value}, ...]}'''&lt;br /&gt;
:指定用于DNS解析的 properties. 允许的 Properties 有: 以秒计的缺省值为10的 timeout 和缺省值为2的重试次数. &lt;br /&gt;
'''{s2s_default_policy, allow|deny}'''&lt;br /&gt;
:对于链入和链出到其他XMPP服务器的s2s连接的缺省策略. 缺省值是 allow. &lt;br /&gt;
'''{{s2s_host, Host}, allow|deny}'''&lt;br /&gt;
:指定是否允许一个特定远程主机的链入和链出s2s连接. 这允许限制 ejabberd 只和少数信任的服务器建立s2s连接, 或禁止一些特定的服务器. &lt;br /&gt;
'''{s2s_max_retry_delay, Seconds}'''&lt;br /&gt;
:连接失败后重试连接的最大允许延迟时间. 以秒计算. 这个缺省值是 300 秒 (5分钟). &lt;br /&gt;
'''{max_fsm_queue, Size}'''&lt;br /&gt;
:这个选项指定FSM(有限状态机)的队列里元素的最大数量. 大概来说, 在这些队列里每个消息展示一个准备发送到它想要的外发的流的XML节. 如果队列大小达到限制(因为, 例如, 节的接收者太慢), 这个FSM和相应的连接(如果有)将被终止并且记录一个出错信息. 这个选项的合理的值依赖于你的硬件配置. 无论如何, 把这个大小设为1000个元素以上应该没什么感觉. 这个选项可被指定给 ejabberd_service 和 ejabberd_c2s listeners, 或也可以全局地指定给 ejabberd_s2s_out. 如果这个选项没有指定给 ejabberd_service 或 ejabberd_c2s listeners, 则使用全局配置的值. 允许的值为整数和 ’undefined’. 缺省值为: ’undefined’.  &lt;br /&gt;
'''{route_subdomains, local|s2s}'''&lt;br /&gt;
:定义 ejabberd 是必须直接把节从本地路由到子域 subdomains(兼容 [[RFC3920|RFC 3920: XMPP核心]]), 还是使用S2S到外部服务器 (兼容 [http://tools.ietf.org/html/draft-saintandre-rfc3920bis-09#section-11.3 RFC 3920 bis]).&lt;br /&gt;
&lt;br /&gt;
=====示例=====&lt;br /&gt;
&lt;br /&gt;
例如, 以下简单配置定义:&lt;br /&gt;
&lt;br /&gt;
* 有三个域. 缺省证书文件是 server.pem. 然而, 连接到域example.com的c2s和s2s使用文件example_com.pem.&lt;br /&gt;
* 端口 5222 使用 STARTTLS 监听 c2s 连接, 同时允许简单连接用于旧的客户端.&lt;br /&gt;
* 端口 5223 使用旧的 SSL 监听 c2s 连接 .&lt;br /&gt;
* 端口 5269 使用 STARTTLS 监听 s2s 连接. 这个socket设为IPv6而不是IPv4.&lt;br /&gt;
* 端口 3478 监听通过 UDP 发出的 STUN 请求 .&lt;br /&gt;
* 端口 5280 监听 HTTP 请求, 并伺服 HTTP 轮询服务.&lt;br /&gt;
* 端口 5281 监听 HTTP 请求, 并使用 HTTPS 伺服 Web Admin (见 [[Ejabberd2:安装和操作指南#Web管理|4.3]] 节). 这个socket只监听来自IP地址127.0.0.1的连接.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{hosts, [&amp;quot;example.com&amp;quot;, &amp;quot;example.org&amp;quot;, &amp;quot;example.net&amp;quot;]}.&lt;br /&gt;
{listen,&lt;br /&gt;
 [&lt;br /&gt;
  {5222, ejabberd_c2s, [&lt;br /&gt;
                        {access, c2s},&lt;br /&gt;
                        {shaper, c2s_shaper},&lt;br /&gt;
                        starttls, {certfile, &amp;quot;/etc/ejabberd/server.pem&amp;quot;},&lt;br /&gt;
                        {max_stanza_size, 65536}&lt;br /&gt;
                       ]},&lt;br /&gt;
  {5223, ejabberd_c2s, [&lt;br /&gt;
                        {access, c2s},&lt;br /&gt;
                        {shaper, c2s_shaper},&lt;br /&gt;
                        tls, {certfile, &amp;quot;/etc/ejabberd/server.pem&amp;quot;},&lt;br /&gt;
                        {max_stanza_size, 65536}&lt;br /&gt;
                       ]},&lt;br /&gt;
  {{5269, &amp;quot;::&amp;quot;}, ejabberd_s2s_in, [&lt;br /&gt;
                                   {shaper, s2s_shaper},&lt;br /&gt;
                                   {max_stanza_size, 131072}&lt;br /&gt;
                                  ]},&lt;br /&gt;
  {{3478, udp}, ejabberd_stun, []},&lt;br /&gt;
  {5280, ejabberd_http, [&lt;br /&gt;
                         http_poll&lt;br /&gt;
                        ]},&lt;br /&gt;
  {{5281, &amp;quot;127.0.0.1&amp;quot;}, ejabberd_http, [&lt;br /&gt;
                                        web_admin,&lt;br /&gt;
                                        tls, {certfile, &amp;quot;/etc/ejabberd/server.pem&amp;quot;},&lt;br /&gt;
                                       ]}&lt;br /&gt;
 ]&lt;br /&gt;
}.&lt;br /&gt;
{s2s_use_starttls, true}.&lt;br /&gt;
{s2s_certfile, &amp;quot;/etc/ejabberd/server.pem&amp;quot;}.&lt;br /&gt;
{domain_certfile, &amp;quot;example.com&amp;quot;, &amp;quot;/etc/ejabberd/example_com.pem&amp;quot;}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在这个例子, 定义了以下配置:&lt;br /&gt;
&lt;br /&gt;
* 端口 5222 (所有IPv4地址)和端口5223 (SSL, IP 192.168.0.1 和 fdca:8ab6:a243:75ef::1)监听c2s连接 ，并禁止名为 ‘bad’的用户.&lt;br /&gt;
* 端口 5269 (所有IPv4地址)为了允许安全通讯而使用STARTTLS监听s2s连接. 远程XMPP服务器的链入和链出连接被禁止, 只有两个服务器可以连接: &amp;quot;jabber.example.org&amp;quot; 和 &amp;quot;example.com&amp;quot;.&lt;br /&gt;
* 端口 5280 在所有的IPv4地址伺服 Web Admin 和 HTTP Polling 服务. 注意它也可能在不同端口伺服它们. [[Ejabberd2:安装和操作指南#Web管理|4.3]] 节的第二个例子展示了怎样确切的做法.&lt;br /&gt;
* 除了管理员，所有用户的通讯流量限制为 1,000 Bytes/second&lt;br /&gt;
* [http://www.ejabberd.im/pyaimt AIM 网关] aim.example.org 被连接到localhost IP 地址(127.0.0.1 and ::1)的 5233 端口 ， 连接密码为‘aimsecret’.&lt;br /&gt;
* ICQ 网关 JIT (icq.example.org and sms.example.org) 被以密码‘jitsecret’连接到端口 5234 .&lt;br /&gt;
* [http://www.ejabberd.im/pymsnt MSN 网关] msn.example.org 被以密码‘msnsecret’连接到端口 5235 .&lt;br /&gt;
* [http://www.ejabberd.im/yahoo-transport-2 Yahoo! 网关] yahoo.example.org 被以密码‘yahoosecret’连接到端口 5236 .&lt;br /&gt;
* [http://www.ejabberd.im/jabber-gg-transport Gadu-Gadu 网关] gg.example.org  被以密码‘ggsecret’连接到端口 5237 .&lt;br /&gt;
* [http://www.ejabberd.im/jmc Jabber Mail 组件] jmc.example.org 被以密码‘jmsecret’连接到端口 5238 .&lt;br /&gt;
* 服务自定义允许特别的选项用来逃避对从这个组件发送的包里检查from属性. 这个组件可以从服务器以任何用户的身份发送包, 或者甚至以任何服务器的身份.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{acl, blocked, {user, &amp;quot;bad&amp;quot;}}.&lt;br /&gt;
{access, c2s, [{deny, blocked},&lt;br /&gt;
               {allow, all}]}.&lt;br /&gt;
{shaper, normal, {maxrate, 1000}}.&lt;br /&gt;
{access, c2s_shaper, [{none, admin},&lt;br /&gt;
                      {normal, all}]}.&lt;br /&gt;
{listen,&lt;br /&gt;
 [{5222, ejabberd_c2s, [&lt;br /&gt;
                        {access, c2s},&lt;br /&gt;
                        {shaper, c2s_shaper}&lt;br /&gt;
                       ]},&lt;br /&gt;
  {{5223, {192, 168, 0, 1}}, ejabberd_c2s, [&lt;br /&gt;
                                            {access, c2s},&lt;br /&gt;
                                            ssl, {certfile, &amp;quot;/path/to/ssl.pem&amp;quot;}&lt;br /&gt;
                                           ]},&lt;br /&gt;
  {{5223, {16#fdca, 16#8ab6, 16#a243, 16#75ef, 0, 0, 0, 1}},&lt;br /&gt;
   ejabberd_c2s, [&lt;br /&gt;
                  {access, c2s},&lt;br /&gt;
                  ssl, {certfile, &amp;quot;/path/to/ssl.pem&amp;quot;}&lt;br /&gt;
                 ]},&lt;br /&gt;
  {5269, ejabberd_s2s_in, []},&lt;br /&gt;
  {{5280, {0, 0, 0, 0}}, ejabberd_http, [&lt;br /&gt;
                                         http_poll,&lt;br /&gt;
                                         web_admin&lt;br /&gt;
                                        ]},&lt;br /&gt;
  {{5233, {127, 0, 0, 1}}, ejabberd_service, [&lt;br /&gt;
                                              {hosts, [&amp;quot;aim.example.org&amp;quot;],&lt;br /&gt;
                                                 [{password, &amp;quot;aimsecret&amp;quot;}]}&lt;br /&gt;
                                             ]},&lt;br /&gt;
  {{5233, &amp;quot;::1&amp;quot;}, ejabberd_service, [&lt;br /&gt;
                                     {hosts, [&amp;quot;aim.example.org&amp;quot;],&lt;br /&gt;
                                        [{password, &amp;quot;aimsecret&amp;quot;}]}&lt;br /&gt;
                                    ]},&lt;br /&gt;
  {5234, ejabberd_service, [{hosts, [&amp;quot;icq.example.org&amp;quot;, &amp;quot;sms.example.org&amp;quot;],&lt;br /&gt;
                             [{password, &amp;quot;jitsecret&amp;quot;}]}]},&lt;br /&gt;
  {5235, ejabberd_service, [{hosts, [&amp;quot;msn.example.org&amp;quot;],&lt;br /&gt;
                             [{password, &amp;quot;msnsecret&amp;quot;}]}]},&lt;br /&gt;
  {5236, ejabberd_service, [{hosts, [&amp;quot;yahoo.example.org&amp;quot;],&lt;br /&gt;
                             [{password, &amp;quot;yahoosecret&amp;quot;}]}]},&lt;br /&gt;
  {5237, ejabberd_service, [{hosts, [&amp;quot;gg.example.org&amp;quot;],&lt;br /&gt;
                             [{password, &amp;quot;ggsecret&amp;quot;}]}]},&lt;br /&gt;
  {5238, ejabberd_service, [{hosts, [&amp;quot;jmc.example.org&amp;quot;],&lt;br /&gt;
                             [{password, &amp;quot;jmcsecret&amp;quot;}]}]},&lt;br /&gt;
  {5239, ejabberd_service, [{hosts, [&amp;quot;custom.example.org&amp;quot;],&lt;br /&gt;
                             [{password, &amp;quot;customsecret&amp;quot;}]},&lt;br /&gt;
                            {service_check_from, false}]}&lt;br /&gt;
 ]&lt;br /&gt;
}.&lt;br /&gt;
{s2s_use_starttls, true}.&lt;br /&gt;
{s2s_certfile, &amp;quot;/path/to/ssl.pem&amp;quot;}.&lt;br /&gt;
{s2s_default_policy, deny}.&lt;br /&gt;
{{s2s_host,&amp;quot;jabber.example.org&amp;quot;}, allow}.&lt;br /&gt;
{{s2s_host,&amp;quot;example.com&amp;quot;}, allow}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
注意, 对基于 jabberd14 或 WPJabber 的服务，你不得不做一个网关日志并通过它们本身做 XDB : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;!--&lt;br /&gt;
     You have to add elogger and rlogger entries here when using ejabberd.&lt;br /&gt;
     In this case the transport will do the logging.&lt;br /&gt;
  --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;log id='logger'&amp;gt;&lt;br /&gt;
    &amp;lt;host/&amp;gt;&lt;br /&gt;
    &amp;lt;logtype/&amp;gt;&lt;br /&gt;
    &amp;lt;format&amp;gt;%d: [%t] (%h): %s&amp;lt;/format&amp;gt;&lt;br /&gt;
    &amp;lt;file&amp;gt;/var/log/jabber/service.log&amp;lt;/file&amp;gt;&lt;br /&gt;
  &amp;lt;/log&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!--&lt;br /&gt;
     Some XMPP server implementations do not provide&lt;br /&gt;
     XDB services (for example, jabberd2 and ejabberd).&lt;br /&gt;
     xdb_file.so is loaded in to handle all XDB requests.&lt;br /&gt;
  --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;xdb id=&amp;quot;xdb&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;host/&amp;gt;&lt;br /&gt;
    &amp;lt;load&amp;gt;&lt;br /&gt;
      &amp;lt;!-- this is a lib of wpjabber or jabberd14 --&amp;gt;&lt;br /&gt;
      &amp;lt;xdb_file&amp;gt;/usr/lib/jabber/xdb_file.so&amp;lt;/xdb_file&amp;gt;&lt;br /&gt;
      &amp;lt;/load&amp;gt;&lt;br /&gt;
    &amp;lt;xdb_file xmlns=&amp;quot;jabber:config:xdb_file&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;spool&amp;gt;&amp;lt;jabberd:cmdline flag='s'&amp;gt;/var/spool/jabber&amp;lt;/jabberd:cmdline&amp;gt;&amp;lt;/spool&amp;gt;&lt;br /&gt;
    &amp;lt;/xdb_file&amp;gt;&lt;br /&gt;
  &amp;lt;/xdb&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
====验证====&lt;br /&gt;
&lt;br /&gt;
选项 auth_method 定义了用于验证用户的验证方法. 语法是:&lt;br /&gt;
&lt;br /&gt;
'''{auth_method, [Method, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
ejabberd支持以下验证方法:&lt;br /&gt;
&lt;br /&gt;
* internal (缺省) — 见 [[Ejabberd2:安装和操作指南#内部|3.1.4.]] 节&lt;br /&gt;
* external — 有[http://www.ejabberd.im/extauth 一些示例验证代码].&lt;br /&gt;
* ldap — 见 [[Ejabberd2:安装和操作指南#LDAP|3.2.5.]] 节&lt;br /&gt;
* odbc — 见 [[Ejabberd2:安装和操作指南#MySQL|3.2.1]], [[Ejabberd2:安装和操作指南#PostgreSQL|3.2.3]], [[Ejabberd2:安装和操作指南# Microsoft SQL Server|3.2.2]] 和 [[Ejabberd2:安装和操作指南#ODBC兼容|3.2.4.]] 节&lt;br /&gt;
* anonymous — 见 [[Ejabberd2:安装和操作指南#SASL匿名和匿名登录|3.1.4.]] 节&lt;br /&gt;
* pam — 见 [[Ejabberd2:安装和操作指南#SASL匿名和匿名登录|3.1.4.]] 节&lt;br /&gt;
&lt;br /&gt;
只有internal 和 odbc 方法支持新建帐号.&lt;br /&gt;
&lt;br /&gt;
=====内部=====&lt;br /&gt;
&lt;br /&gt;
ejabberd使用它的内部Mnesia数据库作为缺省的验证方法. 这个值 internal 将允许内部验证方法.&lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 在example.org使用内部验证, 在example.net使用LDAP验证:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {host_config, &amp;quot;example.org&amp;quot;, [{auth_method, [internal]}]}.&lt;br /&gt;
      {host_config, &amp;quot;example.net&amp;quot;, [{auth_method, [ldap]}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在所有虚拟主机使用内部验证:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {auth_method, internal}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====SASL匿名和匿名登录=====&lt;br /&gt;
&lt;br /&gt;
这个值 anonymous 将允许内部验证方法.&lt;br /&gt;
&lt;br /&gt;
匿名验证方法可以由以下选项配置. 记住你可以用 host_config 选项设置虚拟主机个别特有的选项(见 [[Ejabberd2:安装和操作指南#虚拟主机|3.1.2]] 节). 注意关于[http://support.process-one.net/doc/display/MESSENGER/Anonymous+users+support SASL匿名和匿名登录配置]也有一个详细的教程 .&lt;br /&gt;
&lt;br /&gt;
'''{allow_multiple_connections, false|true}'''&lt;br /&gt;
:这个选项只用于匿名模式已经被允许的时候. 设置它为 true 意味着在匿名登录模式里，如果使用不同的资源来连接，同样的用户名可以被使用多次. 这个选项只在非常特殊的情况下有用. 缺省值是 false. &lt;br /&gt;
'''{anonymous_protocol, sasl_anon | login_anon | both}'''&lt;br /&gt;
:sasl_anon 意味着将使用 SASL 匿名方法. login_anon 意味着将使用匿名登录方法. both 意味着SASL匿名和匿名登录都允许. &lt;br /&gt;
&lt;br /&gt;
那些选项为每个虚拟主机定义的选项 host_config 参数 (见 [[Ejabberd2:安装和操作指南#虚拟主机|3.1.2]] 节).&lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 在所有虚拟主机上允许匿名登录:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {auth_method, [anonymous]}.&lt;br /&gt;
      {anonymous_protocol, login_anon}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 类似前例, 但限于 public.example.org:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {host_config, &amp;quot;public.example.org&amp;quot;, [{auth_method, [anonymous]},&lt;br /&gt;
                                           {anonymous_protocol, login_anon}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在一个虚拟主机允许匿名登录和内部验证:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {host_config, &amp;quot;public.example.org&amp;quot;, [{auth_method, [internal,anonymous]},&lt;br /&gt;
                                           {anonymous_protocol, login_anon}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在一个虚拟主机允许SASL匿名:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {host_config, &amp;quot;public.example.org&amp;quot;, [{auth_method, [anonymous]},&lt;br /&gt;
                                           {anonymous_protocol, sasl_anon}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在一个虚拟主机允许SASL匿名和匿名登录:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {host_config, &amp;quot;public.example.org&amp;quot;, [{auth_method, [anonymous]},&lt;br /&gt;
                                           {anonymous_protocol, both}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在一个虚拟主机允许SASL匿名, 匿名登录, 和内部验证:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {host_config, &amp;quot;public.example.org&amp;quot;, [{auth_method, [internal,anonymous]},&lt;br /&gt;
                                           {anonymous_protocol, both}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====PAM验证=====&lt;br /&gt;
&lt;br /&gt;
ejabberd支持通过可插拔的验证模块(PAM)来验证. PAM 目前在 AIX, FreeBSD, HP-UX, Linux, Mac OS X, NetBSD 和 Solaris里都支持. PAM 验证缺省是被禁止的, 所以你不得不使用 PAM support enabled 选项来配置并编译ejabberd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
./configure --enable-pam &amp;amp;&amp;amp; make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{pam_service, Name}'''&lt;br /&gt;
:这个选项定义了PAM服务名. 缺省是 &amp;quot;ejabberd&amp;quot;. 更多信息请参考你的操作系统的 PAM 文档. &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{auth_method, [pam]}.&lt;br /&gt;
{pam_service, &amp;quot;ejabberd&amp;quot;}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
虽然很容易在ejabberd里配置PAM支持, PAM本身介绍了一些安全问题:&lt;br /&gt;
&lt;br /&gt;
* 为执行PAM验证，ejabberd使用名为 epam 的外部C程序. 缺省的, 它位于 /var/lib/ejabberd/priv/bin/ 目录. 在这个例子里，如果你的PAM模块要求root权限(例如pam_unix.so)，你不得不把它设为root可执行. 你也不得不为ejabberd赋予访问这个文件的权限，并移除所有其他权限. 以root权限执行以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      chown root:ejabberd /var/lib/ejabberd/priv/bin/epam&lt;br /&gt;
      chmod 4750 /var/lib/ejabberd/priv/bin/epam&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 确保你已在你的系统安装了最新版本的PAM. 一些旧版本的PAM模块会导致内存溢出. 如果你不能使用最新版本, 你可以定期杀掉(1) epam 进程以减少它的内存消耗: ejabberd将立刻重启这个进程.&lt;br /&gt;
* epam程序在验证失败时尝试关闭延迟. 然而, 一些PAM模块忽略这个行为并依靠它们自己的配置选项. 你可以新建一个配置文件ejabberd.pam. 这个例子展示如何在pam_unix.so模块关闭延迟:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      #%PAM-1.0&lt;br /&gt;
      auth        sufficient  pam_unix.so likeauth nullok nodelay&lt;br /&gt;
      account     sufficient  pam_unix.so&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:这不是一个已准备好使用的配置文件: 当你建立你自己的PAM配置时，你必须示意使用它. 注意如果你想在PAM配置文见里设置在验证失败时禁止延迟, 你不得不限制访问这个文件, 这样恶意用户就不能使用你的配置来执行暴力攻击.&lt;br /&gt;
* 你可能希望只允许特定用户登录访问. pam_listfile.so 模块提供这个功能.&lt;br /&gt;
* 如果你使用 pam_winbind 来对一个Windows Active Directory授权, 那么 /etc/nssswitch.conf 必须被配置成使用winbind.&lt;br /&gt;
&lt;br /&gt;
====访问规则====&lt;br /&gt;
&lt;br /&gt;
=====ACL定义=====&lt;br /&gt;
&lt;br /&gt;
在ejabberd里访问控制是通过访问控制列表(ACLs)来实现的. 配置文件中ACLs的声明语法如下:&lt;br /&gt;
&lt;br /&gt;
'''{acl, ACLName, ACLValue}.'''&lt;br /&gt;
&lt;br /&gt;
ACLValue 可以是以下之一:&lt;br /&gt;
&lt;br /&gt;
'''all'''&lt;br /&gt;
:匹配所有JIDs. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, all, all}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{user, Username}'''&lt;br /&gt;
:匹配第一个虚拟主机，名字为 Username 的用户. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, admin, {user, &amp;quot;yozhik&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{user, Username, Server}'''&lt;br /&gt;
:匹配JID为Username@Server加任何资源的用户. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, admin, {user, &amp;quot;yozhik&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{server, Server}'''&lt;br /&gt;
:匹配从服务器Server来的任何JID. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, exampleorg, {server, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{resource, Resource}'''&lt;br /&gt;
:匹配任何资源为Resource的JID. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, mucklres, {resource, &amp;quot;muckl&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{shared_group, Groupname}'''&lt;br /&gt;
:匹配这个虚拟主机上的共享名册组Groupname的任何成员. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, techgroupmembers, {shared_group, &amp;quot;techteam&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{shared_group, Groupname, Server}'''&lt;br /&gt;
:匹配虚拟主机Server上的共享名册组Groupname的任何成员. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, techgroupmembers, {shared_group, &amp;quot;techteam&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{user_regexp, Regexp}'''&lt;br /&gt;
:匹配本地虚拟主机（们）上的任何名字符合Regexp的本地用户. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, tests, {user_regexp, &amp;quot;^test[0-9]*$&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{user_regexp, UserRegexp, Server}'''&lt;br /&gt;
:匹配服务器Server上名字符合UserRegexp的任何用户. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, tests, {user_Userregexp, &amp;quot;^test&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{server_regexp, Regexp}'''&lt;br /&gt;
:匹配来自符合server_regexp的服务器的任何JID. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, icq, {server_regexp, &amp;quot;^icq\\.&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{resource_regexp, Regexp}'''&lt;br /&gt;
:匹配资源符合resource_regexp的任何JID. 例子:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, icq, {resource_regexp, &amp;quot;^laptop\\.&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{node_regexp, UserRegexp, ServerRegexp}'''&lt;br /&gt;
:匹配任何名字符合ServerRegexp的服务器上的任何名字符合UserRegexp的用户. Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {acl, yohzik, {node_regexp, &amp;quot;^yohzik$&amp;quot;, &amp;quot;^example.(com|org)$&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''{user_glob, Glob}'''&lt;br /&gt;
'''{user_glob, Glob, Server}'''&lt;br /&gt;
'''{server_glob, Glob}'''&lt;br /&gt;
'''{resource_glob, Glob}'''&lt;br /&gt;
'''{node_glob, UserGlob, ServerGlob}'''&lt;br /&gt;
:这和上面一样. 然而, 它使用 shell glob 模式而不是 regexp. 这些模式能拥有以下特别的字符:&lt;br /&gt;
&lt;br /&gt;
:'''*'''&lt;br /&gt;
::匹配任何包含null字符的字符串. &lt;br /&gt;
:'''    ?'''&lt;br /&gt;
::        匹配任何单个字符. &lt;br /&gt;
:'''    [...]'''&lt;br /&gt;
::匹配任何封闭的字符串. 字符范围由一对使用‘-’分割的字符串定义. 如果在 ‘[’之后的第一个字符是一个‘!’, 匹配任何不封闭的字符. &lt;br /&gt;
&lt;br /&gt;
以下 ACLName 是预定义的:&lt;br /&gt;
&lt;br /&gt;
'''all'''&lt;br /&gt;
:匹配任何JID. &lt;br /&gt;
'''none'''&lt;br /&gt;
:不匹配任何JID.&lt;br /&gt;
&lt;br /&gt;
=====访问权限=====&lt;br /&gt;
&lt;br /&gt;
一个允许或禁止访问不同服务的条目. 语法是:&lt;br /&gt;
&lt;br /&gt;
'''{access, AccessName, [ {allow|deny, ACLName}, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
当一个JID被检查到可以访问 Accessname, 服务器顺序检查是否那个 JID 匹配任何在列表里这一元组的第二个元素命名的 ACLs. 如果匹配, 返回第一个匹配的元组的第一个元素, 否则返回值‘deny’.&lt;br /&gt;
&lt;br /&gt;
如果你在一个虚拟主机定义了特定的访问权限, 记住全局定义的访问权限比它们拥有优先权. 这意味着, 当发生冲突的时候, 使用这个全局服务器上的赋予或禁止访问，而虚拟主机配置的访问控制无效.&lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{access, configure, [{allow, admin}]}.&lt;br /&gt;
{access, something, [{deny, badmans},&lt;br /&gt;
                     {allow, all}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
以下 AccessName 是预定义的:&lt;br /&gt;
&lt;br /&gt;
'''all'''&lt;br /&gt;
:总是返回值‘allow’. &lt;br /&gt;
'''none'''&lt;br /&gt;
:总是返回值‘deny’.&lt;br /&gt;
&lt;br /&gt;
=====使用ACL限制打开的会话=====&lt;br /&gt;
&lt;br /&gt;
特别的 access max_user_sessions 定义了每个用户的会话(已验证的连接)的最大数量. 如果一个用户尝试通过使用不同的资源打开更多的会话, 第一个打开的会话将被断掉连接. 这个 会话替换 的错误信息将被发送到断链的会话. 这个选项的值可能是一个数字, 或 infinity. 缺省值是 infinity.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{access, max_user_sessions, [ {MaxNumber, ACLName}, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
这个例子对所有用户限制每用户会话数为5, 对管理员限制为 10:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{access, max_user_sessions, [{10, admin}, {5, all}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====使用ACL限制到一个远程XMPP服务器的多个连接=====&lt;br /&gt;
&lt;br /&gt;
特别的 access max_s2s_connections 定义了可以建立多少个连接到一个特定的远程XMPP服务器. 缺省值是 infinity. 也可以使用 access max_s2s_connections_per_node.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{access, max_s2s_connections, [ {MaxNumber, ACLName}, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
例子: &lt;br /&gt;
&lt;br /&gt;
* 允许每个远程服务器最多3个连接:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {access, max_s2s_connections, [{3, all}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====整形====&lt;br /&gt;
&lt;br /&gt;
整形允许你限制连接的通讯量. 语法是:&lt;br /&gt;
&lt;br /&gt;
'''{shaper, ShaperName, Kind}.'''&lt;br /&gt;
&lt;br /&gt;
目前只支持一种整形 maxrate . 语法如下:&lt;br /&gt;
&lt;br /&gt;
'''{maxrate, Rate}'''&lt;br /&gt;
&lt;br /&gt;
这里 Rate 代表最大允许每秒收到的字节数. 当一个连接超过了这个限制, ejabberd停止从socket读取，直到平均速率再次降到允许的最大值以下.&lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 定义一个 shaper 名为 ‘normal’ ，限制流量速度为 1,000 bytes/second:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {shaper, normal, {maxrate, 1000}}.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 定义一个 shaper 名为‘fast’，限制流量速度为 50,000 bytes/second:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {shaper, fast, {maxrate, 50000}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====缺省语言====&lt;br /&gt;
&lt;br /&gt;
这个选项 language 定义服务器能被XMPP客户端看到的字符串的缺省语言. 如果一个XMPP客户端不支持 xml:lang, 将使用这里定义的语言.&lt;br /&gt;
&lt;br /&gt;
这个选项的语法是:&lt;br /&gt;
&lt;br /&gt;
'''{language, Language}.'''&lt;br /&gt;
&lt;br /&gt;
缺省值是 en. 为了让它生效，在ejabberd的 msgs 目录必须有一个翻译文件 Language.msg.&lt;br /&gt;
&lt;br /&gt;
例如, 设置俄语为缺省语言:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{language, &amp;quot;ru&amp;quot;}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
附录 [[Ejabberd2:安装和操作指南#附录A 国际化和本地化|A]] 提供了关于国际化和本地化的更多细节.&lt;br /&gt;
&lt;br /&gt;
====CAPTCHA====&lt;br /&gt;
&lt;br /&gt;
一些ejabberd模块可被配置成在特定的动作上要求 CAPTCHA 挑战. 如果客户端不支持 CAPTCHA Forms ([http://xmpp.org/extensions/xep-0158.html XEP-0158]), 将提供一个web连接让用户用web浏览器填写挑战.&lt;br /&gt;
&lt;br /&gt;
提供了一个示例脚本使用 ImageMagick 的转换程序来生成图片 .&lt;br /&gt;
&lt;br /&gt;
配置选项为:&lt;br /&gt;
&lt;br /&gt;
'''{captcha_cmd, Path}'''&lt;br /&gt;
:一个生成图片的脚本的全路径. 缺省值为空: &amp;quot;&amp;quot; &lt;br /&gt;
'''{captcha_host, Host}'''&lt;br /&gt;
:发给用户的 URL 的 Host 部分. 你可以包含端口号. 发给用户的 URL 的格式为: http://Host/captcha/ ,缺省值是第一个被配置的主机名. &lt;br /&gt;
&lt;br /&gt;
另外, 必须允许一个 ejabberd_http 监听者拥有 captcha 选项. 见 [[Ejabberd2:安装和操作指南#监听的模块|3.1.3]] 节.&lt;br /&gt;
&lt;br /&gt;
示例配置:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{hosts, [&amp;quot;example.org&amp;quot;]}.&lt;br /&gt;
&lt;br /&gt;
{captcha_cmd, &amp;quot;/lib/ejabberd/priv/bin/captcha.sh&amp;quot;}.&lt;br /&gt;
{captcha_host, &amp;quot;example.org:5280&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
{listen,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {5280, ejabberd_http, [&lt;br /&gt;
                         captcha,&lt;br /&gt;
                         ...&lt;br /&gt;
                        ]&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====STUN====&lt;br /&gt;
&lt;br /&gt;
ejabberd可以当作一个独立的 STUN 服务器 ([http://tools.ietf.org/html/rfc5389 RFC 5389]). 目前只支持绑定的使用. 在那个角色中，ejabberd 帮助客户端实现 Jingle ICE ([http://xmpp.org/extensions/xep-0176.html XEP-0176]) 支持来发现它们的外部地址和端口.&lt;br /&gt;
&lt;br /&gt;
你应该配置 ejabberd_stun 监听模块，如 [[Ejabberd2:安装和操作指南#监听端口|3.1.3]] 节所述. 如果定义了 certfile 选项, ejabberd 在同一个端口复用TCP连接和通过TCP连接的TLS . 很明显, certfile选项仅为tcp定义. 注意无论如何，支持 TCP 或 TLS over TCP ,对于绑定使用来说不是必需的，对于TURN功能是保留的. 只有udp传输可以随意配置.&lt;br /&gt;
&lt;br /&gt;
示例配置:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{listen,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {{3478, udp}, ejabberd_stun, []},&lt;br /&gt;
  {3478, ejabberd_stun, []},&lt;br /&gt;
  {5349, ejabberd_stun, [{certfile, &amp;quot;/etc/ejabberd/server.pem&amp;quot;}]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]&lt;br /&gt;
}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
你也需要正确地配置 DNS SRV 记录，这样客户端可以很容易地发现一个为你的XMPP域服务的 STUN 服务器. 具体请参考[http://tools.ietf.org/html/rfc5389 RFC 5389]的[http://tools.ietf.org/html/rfc5389#section-9 DNS Discovery of a Server] 章节.&lt;br /&gt;
&lt;br /&gt;
示例 DNS SRV 配置:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
_stun._udp   IN SRV  0 0 3478 stun.example.com.&lt;br /&gt;
_stun._tcp   IN SRV  0 0 3478 stun.example.com.&lt;br /&gt;
_stuns._tcp  IN SRV  0 0 5349 stun.example.com.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====包含其它配置文件====&lt;br /&gt;
&lt;br /&gt;
一个配置文件中的选项 include_config_file 代表 ejabberd 包含了其他配置文件to include other configuration files immediately.&lt;br /&gt;
&lt;br /&gt;
基本语法:&lt;br /&gt;
&lt;br /&gt;
'''{include_config_file, Filename}.'''&lt;br /&gt;
&lt;br /&gt;
使用完整语法还可以指定子选项 suboptions :&lt;br /&gt;
&lt;br /&gt;
'''{include_config_file, Filename, [Suboption, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
filename 可使用绝对路径, 或使用和主 ejabberd 配置文件相关的相对路径. 不能使用通配符. 文件必须存在且可读.&lt;br /&gt;
&lt;br /&gt;
以下子选项 suboptions 为:&lt;br /&gt;
&lt;br /&gt;
'''{disallow, [Optionname, ...]}'''&lt;br /&gt;
:不允许使用那些被包含文件中的选项. 满足这个条件的选项立刻变成不可接受. 缺省值为空列表: [] &lt;br /&gt;
'''{allow_only, [Optionname, ...]}'''&lt;br /&gt;
:只允许使用这个被包含的配置文件中的选项. 不满足这个条件的选项立刻变成不可接受. 缺省值为: all &lt;br /&gt;
&lt;br /&gt;
这是个基本例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{include_config_file, &amp;quot;/etc/ejabberd/additional.cfg&amp;quot;}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在这个例子里, 被包含的文件不允许包含一个监听 listen 选项. 如果出现了这个选项, 该选项将不被接受. 这个文件在主配置文件所在目录的一个子目录中.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{include_config_file, &amp;quot;./example.org/additional_not_listen.cfg&amp;quot;, [{disallow, [listen]}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在这个例子, ejabberd.cfg 定义了一些 ACL 和 Access rules, 然后包含了另一个文件,里面含有其他 rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{acl, admin, {user, &amp;quot;admin&amp;quot;, &amp;quot;localhost&amp;quot;}}.&lt;br /&gt;
{access, announce, [{allow, admin}]}.&lt;br /&gt;
{include_config_file, &amp;quot;/etc/ejabberd/acl_and_access.cfg&amp;quot;, [{allow_only, [acl, access]}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并且文件 acl_and_access.cfg 的内容可能是, 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{acl, admin, {user, &amp;quot;bob&amp;quot;, &amp;quot;localhost&amp;quot;}}.&lt;br /&gt;
{acl, admin, {user, &amp;quot;jan&amp;quot;, &amp;quot;localhost&amp;quot;}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====配置文件中的宏选项====&lt;br /&gt;
&lt;br /&gt;
在ejabberd配置文件中, 有可能为一个值定义一个宏 macro,晚些时候使用这个宏定义一个选项.&lt;br /&gt;
&lt;br /&gt;
一个宏 macro 可用以下语法定义:&lt;br /&gt;
&lt;br /&gt;
'''{define_macro, ’MACRO’, Value}.'''&lt;br /&gt;
&lt;br /&gt;
MACRO 必须被一对单引号包住, 而且所有字母为大写; 检查以下例子. 值必须是任何合法的随意的 Erlang 条目.&lt;br /&gt;
&lt;br /&gt;
macro的第一个定义会被保留的, 同一个macro的其它定义被忽略.&lt;br /&gt;
&lt;br /&gt;
Macros 在包含了额外的配置文件之后会被处理, 所以有可能在知道用法之前就使用定义在被包含的配置文件里的 macros.&lt;br /&gt;
&lt;br /&gt;
不能使用定义在另一个macro里面的macro.&lt;br /&gt;
&lt;br /&gt;
有两个办法使用宏:&lt;br /&gt;
&lt;br /&gt;
'''’MACRO’'''&lt;br /&gt;
:你可以把它当成一个 ejabberd 选项的值, 它将被替换成这个macro之前定义的值. 如果这个 macro 之前没有定义, 程序将崩溃并报错.&lt;br /&gt;
'''{use_macro, ’MACRO’, Defaultvalue}'''&lt;br /&gt;
:使用一个macro,即使它之前没有定义. 如果这个 macro 之前没有定义, 使用缺省值 defaultvalue. 这个用法看起来好像它已被定义并以以下方法使用:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {define_macro, 'MACRO', Defaultvalue}.&lt;br /&gt;
    'MACRO'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这个例子展示一个宏的基本使用:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{define_macro, 'LOG_LEVEL_NUMBER', 5}.&lt;br /&gt;
{loglevel, 'LOG_LEVEL_NUMBER'}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
结果被ejabberd解释执行的选项为: {loglevel, 5}.&lt;br /&gt;
&lt;br /&gt;
这个例子展示值可以是任意的Erlang条目:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{define_macro, 'USERBOB', {user, &amp;quot;bob&amp;quot;, &amp;quot;localhost&amp;quot;}}.&lt;br /&gt;
{acl, admin, 'USERBOB'}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
结果被ejabberd解释执行的选项为: {acl, admin, {user, &amp;quot;bob&amp;quot;, &amp;quot;localhost&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
这个复杂的例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{define_macro, 'NUMBER_PORT_C2S', 5222}.&lt;br /&gt;
{define_macro, 'PORT_S2S_IN', {5269, ejabberd_s2s_in, []}}.&lt;br /&gt;
{listen,&lt;br /&gt;
 [&lt;br /&gt;
  {'NUMBER_PORT_C2S', ejabberd_c2s, []},&lt;br /&gt;
  'PORT_S2S_IN',&lt;br /&gt;
  {{use_macro, 'NUMBER_PORT_HTTP', 5280}, ejabberd_http, []}&lt;br /&gt;
 ]&lt;br /&gt;
}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在解释执行之后结果为:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{listen,&lt;br /&gt;
 [&lt;br /&gt;
  {5222, ejabberd_c2s, []},&lt;br /&gt;
  {5269, ejabberd_s2s_in, []},&lt;br /&gt;
  {5280, ejabberd_http, []}&lt;br /&gt;
 ]&lt;br /&gt;
}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===数据库和LDAP配置===&lt;br /&gt;
&lt;br /&gt;
ejabberd缺省使用它内部的 Mnesia 数据库. 然而, 也可能使用关系数据库或一个LDAP服务器来存储持久信息, 长时间存在的数据. ejabberd是非常弹性的: 你可以为不同的虚拟主机配置不同的验证方法, 你可以为相同的主机配置不同的验证机制(fallback), 你可以为模块设置不同的存储系统, 此外.&lt;br /&gt;
&lt;br /&gt;
ejabberd支持以下数据库:&lt;br /&gt;
&lt;br /&gt;
* [http://www.microsoft.com/sql/ Microsoft SQL Server]&lt;br /&gt;
* [http://www.erlang.org/doc/apps/mnesia/index.html Mnesia]&lt;br /&gt;
* [http://www.mysql.com/ MySQL]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Open_Database_Connectivity 任何ODBC兼容数据库]&lt;br /&gt;
* [http://www.postgresql.org/ PostgreSQL]&lt;br /&gt;
&lt;br /&gt;
以下 LDAP 服务器已经过ejabberd测试:&lt;br /&gt;
&lt;br /&gt;
* [http://www.microsoft.com/activedirectory/ Active Directory] (见 [[Ejabberd2:安装和操作指南#Active Directory|3.2.5]] 节)&lt;br /&gt;
* [http://www.openldap.org/ OpenLDAP]&lt;br /&gt;
* 通常任何LDAP兼容服务器都应该可以; 通知我们关于你以不在列表中的服务器的成功例子以便我们列在这里. &lt;br /&gt;
&lt;br /&gt;
关于虚拟主机，特别注意: 如果你在ejabberd.cfg (见 [[Ejabberd2:安装和操作指南#主机名|3.1.1]] 节) 定义了多个域, 你可能希望每个虚拟主机配置不同的数据库, 验证和存储, 这样在两个虚拟主机之间用户名就不会冲突和混淆. 为此, 下一节的选项描述了必须在每个虚拟主机的 host_config 内部配置 (见 [[Ejabberd2:安装和操作指南#虚拟主机|3.1.2]] 节). 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{host_config, &amp;quot;public.example.org&amp;quot;, [&lt;br /&gt;
  {odbc_server, {pgsql, &amp;quot;localhost&amp;quot;, &amp;quot;database-public-example-org&amp;quot;, &amp;quot;ejabberd&amp;quot;, &amp;quot;password&amp;quot;}},&lt;br /&gt;
  {auth_method, [odbc]}&lt;br /&gt;
]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====MySQL====&lt;br /&gt;
&lt;br /&gt;
尽管这一节将描述当你想使用原生的 MySQL驱动时 ejabberd 的配置, 它将不描述MySQL的安装和数据库的建立. 查看MySQL文档和教程 [http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver 在ejabberd使用MySQL原生驱动] 获得关于这些话题的信息. 注意该教程中包含的关于ejabberd的配置和本节是重复的.&lt;br /&gt;
&lt;br /&gt;
而且, 目录 src/odbc 中的文件 mysql.sql 可能你会感兴趣. 这个文件包含ejabberd用于MySQL的schema. 该文件的结尾你可找到更新你的数据库架构schema的信息.&lt;br /&gt;
&lt;br /&gt;
=====驱动编译=====&lt;br /&gt;
&lt;br /&gt;
你可忽略此步骤，如果你已经使用ejabberd的二进制包安装了ejabberd，并使用了内含的MySQL支持.&lt;br /&gt;
&lt;br /&gt;
# 首先, 安装 [http://support.process-one.net/doc/display/CONTRIBS/Yxa Erlang MySQL 库]. 确保被编译的文件在你的 Erlang 路径中; 你可以把它们放到和你的ejabberd .beam 文件相同的目录.&lt;br /&gt;
# 然后, 以允许支持 ODBC 的选项配置并安装 ejabberd (这也需要原生 MySQL 支持!). 为此, 使用以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ./configure --enable-odbc &amp;amp;&amp;amp; make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====数据库连接=====&lt;br /&gt;
&lt;br /&gt;
实际的数据库访问使用选项 odbc_server 来定义. 它的值通常用来定义我们是否想使用 ODBC, 或两个可用的原生接口之一, PostgreSQL 或 MySQL.&lt;br /&gt;
&lt;br /&gt;
为使用原生 MySQL 接口, 你可以通过一组如以下格式的参数:&lt;br /&gt;
&lt;br /&gt;
'''{mysql, &amp;quot;Server&amp;quot;, &amp;quot;Database&amp;quot;, &amp;quot;Username&amp;quot;, &amp;quot;Password&amp;quot;}'''&lt;br /&gt;
&lt;br /&gt;
mysql是一个关键字应该被保持. 例如:&lt;br /&gt;
&lt;br /&gt;
'''{odbc_server, {mysql, &amp;quot;localhost&amp;quot;, &amp;quot;test&amp;quot;, &amp;quot;root&amp;quot;, &amp;quot;password&amp;quot;}}.'''&lt;br /&gt;
&lt;br /&gt;
可选的, 有可能定义MySQL使用的端口. 这个选项只是在非常少的情况下有用, 当你没有以缺省端口设置来运行MySQL时. mysql参数可能是以下格式:&lt;br /&gt;
&lt;br /&gt;
'''{mysql, &amp;quot;Server&amp;quot;, Port, &amp;quot;Database&amp;quot;, &amp;quot;Username&amp;quot;, &amp;quot;Password&amp;quot;}'''&lt;br /&gt;
&lt;br /&gt;
Port值应该是一个整数, 没有引号. 例如:&lt;br /&gt;
&lt;br /&gt;
'''{odbc_server, {mysql, &amp;quot;localhost&amp;quot;, Port, &amp;quot;test&amp;quot;, &amp;quot;root&amp;quot;, &amp;quot;password&amp;quot;}}.'''&lt;br /&gt;
&lt;br /&gt;
缺省的ejabberd为每个虚拟主机打开10个到数据库的连接. 使用这个选项来修改该值:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{odbc_pool_size, 10}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
你可以配置一个时间间隔来做一个假的SQL请求以保持到数据库的连接激活. 缺省值为 ’undefined’, 所以没有做 keepalive 请求. 指定以秒计: 例如 28800 意味着 8 小时.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{odbc_keepalive_interval, undefined}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果到数据库的连接失败, ejabberd在重试之前等待30秒. 你可以这个选项修改这个间隔:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{odbc_start_interval, 30}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====验证=====&lt;br /&gt;
&lt;br /&gt;
这个选项值的名字可能被误导, 因为 auth_method 名字用于通过ODBC以及通过原生MySQL接口访问关系数据库. 无论如何, 第一个配置步骤是定义 odbc auth_method. 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{auth_method, [odbc]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====存储=====&lt;br /&gt;
&lt;br /&gt;
MySQL也能被从多个ejabberd模块用于存储信息. 见 [[Ejabberd2:安装和操作指南#模块一览|3.3.1]] 节看哪个模块有一个带‘_odbc’的版本. 这个后缀代表这个模块可以被用于类似MySQL的关系数据库. 为激活你的数据库的存储, 只要确保你的数据库运行正常 (见前一节), 并把不带后缀或ldap模块变量换成带有 odbc 的模块变量. 注意在同一个装载的模块里你不能有多个变量!&lt;br /&gt;
&lt;br /&gt;
====Microsoft SQL Server====&lt;br /&gt;
&lt;br /&gt;
尽管本节将描述当你想使用Microsoft SQL Server时ejabberd的配置, 它不描述Microsoft SQL Server的安装和数据库创建. 查看MySQL文档和教程 [http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver 在ejabberd使用MySQL原生驱动] 获得关于这些话题的信息. 注意该教程中包含的关于ejabberd的配置和本节是重复的.&lt;br /&gt;
&lt;br /&gt;
而且, 目录 src/odbc 中的文件 mssql.sql 可能你会感兴趣. 这个文件包含ejabberd用于Microsoft SQL Server的schema. 该文件的结尾你可找到更新你的数据库架构schema的信息.&lt;br /&gt;
&lt;br /&gt;
=====驱动编译=====&lt;br /&gt;
&lt;br /&gt;
你可忽略此步骤，如果你已经使用ejabberd的二进制包安装了ejabberd，并使用了内含的ODBC支持.&lt;br /&gt;
&lt;br /&gt;
如果你想以ODBC方式使用Microsoft SQL Server, 你需要以支持ODBC和允许Microsoft SQL Server选项来配置, 编译和安装 ejabberd. 为此, 使用以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
./configure --enable-odbc --enable-mssql &amp;amp;&amp;amp; make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====数据库连接=====&lt;br /&gt;
&lt;br /&gt;
一个Microsoft SQL Server数据库连接的配置和为一个ODBC兼容服务器的配置相同 (见 [[Ejabberd2:安装和操作指南#ODBC兼容|3.2.4]] 节).&lt;br /&gt;
&lt;br /&gt;
=====验证=====&lt;br /&gt;
&lt;br /&gt;
一个Microsoft SQL Server数据库验证的配置和为一个ODBC兼容服务器的配置相同 (见 [[Ejabberd2:安装和操作指南#ODBC兼容|3.2.4]] 节).&lt;br /&gt;
&lt;br /&gt;
=====存储=====&lt;br /&gt;
&lt;br /&gt;
Microsoft SQL Server也可以被多个ejabberd模块用于存储信息. 见 [[Ejabberd2:安装和操作指南#模块一览|3.3.1]] 节看看哪个模块有一个带‘_odbc’的版本. 这个后缀代表这个模块可以被用于类似Microsoft SQL Server的关系数据库. 为激活你的数据库的存储, 只要确保你的数据库运行正常 (见前一节), 并把不带后缀或ldap模块变量换成带有 odbc 的模块变量. 注意在同一个装载的模块里你不能有多个变量!&lt;br /&gt;
&lt;br /&gt;
====PostgreSQL====&lt;br /&gt;
&lt;br /&gt;
尽管本节将描述当你想使用原生的PostgreSQL驱动时ejabberd的配置, 它不描述PostgreSQL的安装和数据库创建. 查看PostgreSQL文档和教程 [http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver 在ejabberd使用MySQL原生驱动] 获得关于这些话题的信息. 注意该教程中包含的关于ejabberd的配置和本节是重复的.&lt;br /&gt;
&lt;br /&gt;
而且, 目录 src/odbc 中的文件 pg.sql 可能你会感兴趣. 这个文件包含ejabberd用于PostgreSQL的schema. 该文件的结尾你可找到更新你的数据库架构schema的信息.&lt;br /&gt;
&lt;br /&gt;
=====驱动编译=====&lt;br /&gt;
&lt;br /&gt;
你可忽略此步骤，如果你已经使用ejabberd的二进制包安装了ejabberd，并包含了对PostgreSQL的支持.&lt;br /&gt;
&lt;br /&gt;
# 首先, 从 [http://www.ejabberd.im/ejabberd-modules/  ejabberd-modules SVN 仓库]安装 Erlang pgsql 库. 确保被编译的文件在你的 Erlang 路径中; 你可以把它们放到和你的ejabberd .beam 文件相同的目录.&lt;br /&gt;
# 然后, 以允许支持 ODBC 的选项配置并安装 ejabberd (对于原生的 PostgreSQL 支持这也是必需的!). 为此, 使用以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ./configure --enable-odbc &amp;amp;&amp;amp; make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====数据库连接=====&lt;br /&gt;
&lt;br /&gt;
实际的数据库访问使用选项 odbc_server 来定义. 它的值通常用来定义我们是否想使用 ODBC, 或两个可用的原生接口之一, PostgreSQL 或 MySQL.&lt;br /&gt;
&lt;br /&gt;
为使用原生 PostgreSQL 接口, 你可以通过一组如以下格式的参数:&lt;br /&gt;
&lt;br /&gt;
'''{pgsql, &amp;quot;Server&amp;quot;, &amp;quot;Database&amp;quot;, &amp;quot;Username&amp;quot;, &amp;quot;Password&amp;quot;}'''&lt;br /&gt;
&lt;br /&gt;
pgsql是一个关键字应该被保持. 例如:&lt;br /&gt;
&lt;br /&gt;
'''{odbc_server, {pgsql, &amp;quot;localhost&amp;quot;, &amp;quot;database&amp;quot;, &amp;quot;ejabberd&amp;quot;, &amp;quot;password&amp;quot;}}.'''&lt;br /&gt;
&lt;br /&gt;
可选的, 有可能定义PostgreSQL使用的端口. 这个选项只是在非常少的情况下有用, 当你没有以缺省端口设置来运行PostgreSQL时. pgsql参数可能是以下格式:&lt;br /&gt;
&lt;br /&gt;
'''{pgsql, &amp;quot;Server&amp;quot;, Port, &amp;quot;Database&amp;quot;, &amp;quot;Username&amp;quot;, &amp;quot;Password&amp;quot;}'''&lt;br /&gt;
&lt;br /&gt;
Port值应该是一个整数, 没有引号. 例如:&lt;br /&gt;
&lt;br /&gt;
'''{odbc_server, {pgsql, &amp;quot;localhost&amp;quot;, 5432, &amp;quot;database&amp;quot;, &amp;quot;ejabberd&amp;quot;, &amp;quot;password&amp;quot;}}.'''&lt;br /&gt;
&lt;br /&gt;
缺省的ejabberd为每个虚拟主机打开10个到数据库的连接. 使用这个选项来修改该值:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{odbc_pool_size, 10}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
你可以配置一个时间间隔来做一个假的SQL请求以保持到数据库的连接激活. 缺省值为 ’undefined’, 所以没有做 keepalive 请求. 指定以秒计: 例如 28800 意味着 8 小时.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{odbc_keepalive_interval, undefined}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====验证=====&lt;br /&gt;
&lt;br /&gt;
这个选项值的名字可能被误导, 因为 auth_method 名字用于通过ODBC以及通过原生PostgreSQL接口访问关系数据库. 无论如何, 第一个配置步骤是定义 odbc auth_method. 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{auth_method, [odbc]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====存储=====&lt;br /&gt;
&lt;br /&gt;
PostgreSQL也能被多个ejabberd模块用于存储信息. 见 [[Ejabberd2:安装和操作指南#模块一览|3.3.1]] 节看哪个模块有一个带‘_odbc’的版本. 这个后缀代表这个模块可以被用于类似PostgreSQL的关系数据库. 为激活你的数据库的存储, 只要确保你的数据库运行正常 (见前一节), 并把不带后缀或ldap模块变量换成带有 odbc 的模块变量. 注意在同一个装载的模块里你不能有多个变量!&lt;br /&gt;
&lt;br /&gt;
====ODBC兼容====&lt;br /&gt;
&lt;br /&gt;
尽管本节将描述当你想使用原生的ODBC 驱动时ejabberd的配置, 它不描述安装和数据库创建. 查看你的数据库的文档. 教程 [http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver 在ejabberd使用MySQL原生驱动] 也会对你有所帮助. 注意该教程中包含的关于ejabberd的配置和本节是重复的.&lt;br /&gt;
&lt;br /&gt;
=====驱动编译=====&lt;br /&gt;
&lt;br /&gt;
你可忽略此步骤，如果你已经使用ejabberd的二进制包安装了ejabberd，并包含了对ODBC的支持.&lt;br /&gt;
&lt;br /&gt;
# 首先, 安装 [http://support.process-one.net/doc/display/CONTRIBS/Yxa Erlang MySQL 库] . 确保被编译的文件在你的 Erlang 路径中; 你可以把它们放到和你的ejabberd .beam 文件相同的目录.&lt;br /&gt;
# 然后, 以允许支持 ODBC 的选项配置并安装 ejabberd. 为此, 使用以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ./configure --enable-odbc &amp;amp;&amp;amp; make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====数据库连接=====&lt;br /&gt;
&lt;br /&gt;
实际的数据库访问使用选项 odbc_server 来定义. 它的值通常用来定义我们是否想使用 ODBC, 或两个可用的原生接口之一, PostgreSQL 或 MySQL.&lt;br /&gt;
&lt;br /&gt;
通过ODBC使用数据库, 你可以通过一个ODBC连接字符串作为odbc_server参数. 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{odbc_server, &amp;quot;DSN=database;UID=ejabberd;PWD=password&amp;quot;}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
缺省的ejabberd为每个虚拟主机打开10个到数据库的连接. 使用这个选项来修改该值:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{odbc_pool_size, 10}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
你可以配置一个时间间隔来做一个假的SQL请求以保持到数据库的连接激活. 缺省值为 ’undefined’, 所以没有做 keepalive 请求. 指定以秒计: 例如 28800 意味着 8 小时.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{odbc_keepalive_interval, undefined}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====验证=====&lt;br /&gt;
&lt;br /&gt;
第一个配置步骤是定义 odbc auth_method. 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{auth_method, [odbc]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====存储=====&lt;br /&gt;
&lt;br /&gt;
一个ODBC兼容数据库也能被多个ejabberd模块用于存储信息. 见 [[Ejabberd2:安装和操作指南#模块一览|3.3.1]] 节看哪个模块有一个带‘_odbc’的版本. 这个后缀代表这个模块可以被用于ODBC兼容的关系数据库. 为激活你的数据库的存储, 只要确保你的数据库运行正常 (见前一节), 并把不带后缀或ldap模块变量换成带有 odbc 的模块变量. 注意在同一个装载的模块里你不能有多个变量!&lt;br /&gt;
&lt;br /&gt;
====LDAP====&lt;br /&gt;
&lt;br /&gt;
ejabberd拥有内建的LDAP支持. 你可以通过LDAP服务器验证用户并使用LDAP目录作为vCard存储器. 共享名册还不支持.&lt;br /&gt;
&lt;br /&gt;
通常ejabberd把LDAP看作一个只读存储: 它可能察看数据, 但不能新建账号或修改存储在LDAP里的vCard. 然而, 修改密码是可能的，如果允许 mod_register 模块并且LDAP服务器支持[http://tools.ietf.org/html/rfc3062 RFC 3062].&lt;br /&gt;
&lt;br /&gt;
=====连接=====&lt;br /&gt;
&lt;br /&gt;
参数:&lt;br /&gt;
&lt;br /&gt;
'''{ldap_servers, [Servers, ...]}'''&lt;br /&gt;
:你的LDAP服务器的IP地址或DNS名的列表 . 这个选项时必需的. &lt;br /&gt;
'''{ldap_encrypt, none|tls}'''&lt;br /&gt;
:到LDAP服务器的连接的加密类型. 允许的值为: none, tls. 这个值 tls 允许使用SSL加密LDAP连接. 注意 STARTTLS 加密是不支持的. 缺省值为: none. &lt;br /&gt;
'''{ldap_tls_verify, false|soft|hard}'''&lt;br /&gt;
:这个选项指定当允许TLS时是否验证LDAP服务器证书. 当选项值为 hard，如果证书非法，ejabberd 不继续往下走. 当选项值为 soft，即使检查失败ejabberd仍继续下去. 缺省值为 false，它意味着不执行检查. &lt;br /&gt;
'''{ldap_port, Number}'''&lt;br /&gt;
:连接到你的LDAP服务器的端口. 如果禁止加密,缺省端口为389; 如果允许加密则为636. 如果你配置了一个值, 它存储在 ejabberd的数据库里. 接着, 如果你从这个配置文件移除这个值, 之前存储在数据库的值将被缺省端口取代. &lt;br /&gt;
'''{ldap_rootdn, RootDN}'''&lt;br /&gt;
:绑定的DN. 缺省值为&amp;quot;&amp;quot;, 它表示匿名连接 ‘anonymous connection’. &lt;br /&gt;
'''{ldap_password, Password}'''&lt;br /&gt;
:绑定密码 password. 缺省值为 &amp;quot;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{auth_method, ldap}.&lt;br /&gt;
{ldap_servers, [&amp;quot;ldap.example.org&amp;quot;]}.&lt;br /&gt;
{ldap_port, 389}.&lt;br /&gt;
{ldap_rootdn, &amp;quot;cn=Manager,dc=domain,dc=org&amp;quot;}.&lt;br /&gt;
{ldap_password, &amp;quot;secret&amp;quot;}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
注意目前的LDAP实现不支持SASL验证.&lt;br /&gt;
&lt;br /&gt;
=====验证=====&lt;br /&gt;
&lt;br /&gt;
你可以通过LDAP目录验证用户. 可用的选项有:&lt;br /&gt;
&lt;br /&gt;
'''{ldap_base, Base}'''&lt;br /&gt;
:LDAP存储用户的帐号的基础目录. 这个选项是必需的. &lt;br /&gt;
'''{ldap_uids, [ {ldap_uidattr} | {ldap_uidattr, ldap_uidattr_format}, ...]}'''&lt;br /&gt;
:从中可以获得JID的LDAP属性的列表. 缺省属性为 [{&amp;quot;uid&amp;quot;, &amp;quot;%u&amp;quot;}]. 属性的格式为: [{ldap_uidattr}] 或 [{ldap_uidattr, ldap_uidattr_format}]. 你可以使用多个逗号来分隔需要的属性. ldap_uidattr 和 ldap_uidattr_format 的值描述如下:&lt;br /&gt;
&lt;br /&gt;
:'''ldap_uidattr'''&lt;br /&gt;
::存有JID的user部分的LDAP属性. 缺省值为&amp;quot;uid&amp;quot;. &lt;br /&gt;
:'''ldap_uidattr_format'''&lt;br /&gt;
::ldap_uidattr变量的格式. 这个格式必须包含一个并且只有一个 pattern 变量 &amp;quot;%u&amp;quot;，它将由JID的suer部分替换. 例如,&amp;quot;%u@example.org&amp;quot;. 缺省值为 &amp;quot;%u&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
'''{ldap_filter, Filter}'''&lt;br /&gt;
:[http://tools.ietf.org/html/rfc4515 RFC 4515] LDAP过滤器. 缺省的 Filter 值为: undefined. 例子: &amp;quot;(&amp;amp;(objectClass=shadowAccount)(memberOf=Jabber Users))&amp;quot;. 请, 不要忘记关闭括号并且不要用多余的空格. 在过滤器里你也必须不使用ldap_uidattr属性，因为这个属性将被LDAP filter自动取代. &lt;br /&gt;
'''{ldap_dn_filter, { Filter, FilterAttrs }}'''&lt;br /&gt;
:应用于主过滤器返回的结果的过滤器. 这个filter执行额外的LDAP搜索以得到完整的结果. 当你无法在ldap_filter里定义所有filter rule时这是有用的. 你可以在Filter定义 &amp;quot;%u&amp;quot;, &amp;quot;%d&amp;quot;, &amp;quot;%s&amp;quot; and &amp;quot;%D&amp;quot; pattern 变量: &amp;quot;%u&amp;quot; 被用户的JID的user部分替代, &amp;quot;%d&amp;quot; 被相应的域(虚拟主机)替代, 所有 &amp;quot;%s&amp;quot; 变量被FilterAttrs属性值连续地替代，&amp;quot;%D&amp;quot; 被 Distinguished Name(DN) 替代. 缺省的，ldap_dn_filter 为 undefined. 例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {ldap_dn_filter, {&amp;quot;(&amp;amp;(name=%s)(owner=%D)(user=%u@%d))&amp;quot;, [&amp;quot;sn&amp;quot;]}}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:因为这个filter做了额外的LDAP lookups, 只在最后排序时使用它: 如果可能，尝试在 ldap_filter里定义所有 filter rules . &lt;br /&gt;
'''{ldap_local_filter, Filter}'''&lt;br /&gt;
:如果因为性能原因 (该 LDAP 服务器有很多注册用户)你不能使用 ldap_filter , 你可以使用这个本地 filter. local filter 在ejabberd检查一个属性, 而不是 LDAP, 所以限制了这个LDAP目录的负载. 缺省 filter 是: undefined. 示例值:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {ldap_local_filter, {notequal, {&amp;quot;accountStatus&amp;quot;,[&amp;quot;disabled&amp;quot;]}}}.&lt;br /&gt;
    {ldap_local_filter, {equal, {&amp;quot;accountStatus&amp;quot;,[&amp;quot;enabled&amp;quot;]}}}.&lt;br /&gt;
    {ldap_local_filter, undefined}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====示例=====&lt;br /&gt;
&lt;br /&gt;
======普通示例======&lt;br /&gt;
&lt;br /&gt;
让我们以 ldap.example.org 作为我们的 LDAP 服务器名. 我们在 &amp;quot;ou=Users,dc=example,dc=org&amp;quot; 目录使用他们的密码. 同时我们有 addressbook, 在 &amp;quot;ou=AddressBook,dc=example,dc=org&amp;quot; 目录它包含了用户的 emails 和他们的其他信息 . 到LDAP服务器的连接使用TLS加密, 并且使用自定义端口 6123. 相应的验证节应该看起来象这样:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
%% Authentication method&lt;br /&gt;
{auth_method, ldap}.&lt;br /&gt;
%% DNS name of our LDAP server&lt;br /&gt;
{ldap_servers, [&amp;quot;ldap.example.org&amp;quot;]}.&lt;br /&gt;
%% Bind to LDAP server as &amp;quot;cn=Manager,dc=example,dc=org&amp;quot; with password &amp;quot;secret&amp;quot;&lt;br /&gt;
{ldap_rootdn, &amp;quot;cn=Manager,dc=example,dc=org&amp;quot;}.&lt;br /&gt;
{ldap_password, &amp;quot;secret&amp;quot;}.&lt;br /&gt;
{ldap_encrypt, tls}.&lt;br /&gt;
{ldap_port, 6123}.&lt;br /&gt;
%% Define the user's base&lt;br /&gt;
{ldap_base, &amp;quot;ou=Users,dc=example,dc=org&amp;quot;}.&lt;br /&gt;
%% We want to authorize users from 'shadowAccount' object class only&lt;br /&gt;
{ldap_filter, &amp;quot;(objectClass=shadowAccount)&amp;quot;}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
现在我们想使用用户的 LDAP-info 作为他们的 vCards. 在我们的 LDAP schema定义了四个属性: &amp;quot;mail&amp;quot; — email地址, &amp;quot;givenName&amp;quot; — 名, &amp;quot;sn&amp;quot; — 姓, &amp;quot;birthDay&amp;quot; — 生日. 我们也想用户搜索到每个其他人. 我们看如何设置:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_vcard_ldap,&lt;br /&gt;
   [&lt;br /&gt;
    %% We use the same server and port, but want to bind anonymously because&lt;br /&gt;
    %% our LDAP server accepts anonymous requests to&lt;br /&gt;
    %% &amp;quot;ou=AddressBook,dc=example,dc=org&amp;quot; subtree.&lt;br /&gt;
    {ldap_rootdn, &amp;quot;&amp;quot;},&lt;br /&gt;
    {ldap_password, &amp;quot;&amp;quot;},&lt;br /&gt;
    %% define the addressbook's base&lt;br /&gt;
    {ldap_base, &amp;quot;ou=AddressBook,dc=example,dc=org&amp;quot;},&lt;br /&gt;
    %% uidattr: user's part of JID is located in the &amp;quot;mail&amp;quot; attribute&lt;br /&gt;
    %% uidattr_format: common format for our emails&lt;br /&gt;
    {ldap_uids, [{&amp;quot;mail&amp;quot;, &amp;quot;%u@mail.example.org&amp;quot;}]},&lt;br /&gt;
    %% We have to define empty filter here, because entries in addressbook does not&lt;br /&gt;
    %% belong to shadowAccount object class&lt;br /&gt;
    {ldap_filter, &amp;quot;&amp;quot;},&lt;br /&gt;
    %% Now we want to define vCard pattern&lt;br /&gt;
    {ldap_vcard_map,&lt;br /&gt;
     [{&amp;quot;NICKNAME&amp;quot;, &amp;quot;%u&amp;quot;, []}, % just use user's part of JID as his nickname&lt;br /&gt;
      {&amp;quot;GIVEN&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;givenName&amp;quot;]},&lt;br /&gt;
      {&amp;quot;FAMILY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;sn&amp;quot;]},&lt;br /&gt;
      {&amp;quot;FN&amp;quot;, &amp;quot;%s, %s&amp;quot;, [&amp;quot;sn&amp;quot;, &amp;quot;givenName&amp;quot;]}, % example: &amp;quot;Smith, John&amp;quot;&lt;br /&gt;
      {&amp;quot;EMAIL&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;mail&amp;quot;]},&lt;br /&gt;
      {&amp;quot;BDAY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;birthDay&amp;quot;]}]},&lt;br /&gt;
    %% Search form&lt;br /&gt;
    {ldap_search_fields,&lt;br /&gt;
     [{&amp;quot;User&amp;quot;, &amp;quot;%u&amp;quot;},&lt;br /&gt;
      {&amp;quot;Name&amp;quot;, &amp;quot;givenName&amp;quot;},&lt;br /&gt;
      {&amp;quot;Family Name&amp;quot;, &amp;quot;sn&amp;quot;},&lt;br /&gt;
      {&amp;quot;Email&amp;quot;, &amp;quot;mail&amp;quot;},&lt;br /&gt;
      {&amp;quot;Birthday&amp;quot;, &amp;quot;birthDay&amp;quot;}]},&lt;br /&gt;
    %% vCard fields to be reported&lt;br /&gt;
    %% Note that JID is always returned with search results&lt;br /&gt;
    {ldap_search_reported,&lt;br /&gt;
     [{&amp;quot;Full Name&amp;quot;, &amp;quot;FN&amp;quot;},&lt;br /&gt;
      {&amp;quot;Nickname&amp;quot;, &amp;quot;NICKNAME&amp;quot;},&lt;br /&gt;
      {&amp;quot;Birthday&amp;quot;, &amp;quot;BDAY&amp;quot;}]}&lt;br /&gt;
  ]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
注意 mod_vcard_ldap 模块在LDAP搜索用户的信息之前会先检查用户是否存在.&lt;br /&gt;
&lt;br /&gt;
======Active Directory======&lt;br /&gt;
&lt;br /&gt;
Active Directory 只是一个预定义属性的LDAP-服务器. 示范配置如下:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{auth_method, ldap}.&lt;br /&gt;
{ldap_servers, [&amp;quot;office.org&amp;quot;]}.    % List of LDAP servers&lt;br /&gt;
{ldap_base, &amp;quot;DC=office,DC=org&amp;quot;}. % Search base of LDAP directory&lt;br /&gt;
{ldap_rootdn, &amp;quot;CN=Administrator,CN=Users,DC=office,DC=org&amp;quot;}. % LDAP manager&lt;br /&gt;
{ldap_password, &amp;quot;*******&amp;quot;}. % Password to LDAP manager&lt;br /&gt;
{ldap_uids, [{&amp;quot;sAMAccountName&amp;quot;}]}.&lt;br /&gt;
{ldap_filter, &amp;quot;(memberOf=*)&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_vcard_ldap,&lt;br /&gt;
   [{ldap_vcard_map,&lt;br /&gt;
     [{&amp;quot;NICKNAME&amp;quot;, &amp;quot;%u&amp;quot;, []},&lt;br /&gt;
      {&amp;quot;GIVEN&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;givenName&amp;quot;]},&lt;br /&gt;
      {&amp;quot;MIDDLE&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;initials&amp;quot;]},&lt;br /&gt;
      {&amp;quot;FAMILY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;sn&amp;quot;]},&lt;br /&gt;
      {&amp;quot;FN&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;displayName&amp;quot;]},&lt;br /&gt;
      {&amp;quot;EMAIL&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;mail&amp;quot;]},&lt;br /&gt;
      {&amp;quot;ORGNAME&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;company&amp;quot;]},&lt;br /&gt;
      {&amp;quot;ORGUNIT&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;department&amp;quot;]},&lt;br /&gt;
      {&amp;quot;CTRY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;c&amp;quot;]},&lt;br /&gt;
      {&amp;quot;LOCALITY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;l&amp;quot;]},&lt;br /&gt;
      {&amp;quot;STREET&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;streetAddress&amp;quot;]},&lt;br /&gt;
      {&amp;quot;REGION&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;st&amp;quot;]},&lt;br /&gt;
      {&amp;quot;PCODE&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;postalCode&amp;quot;]},&lt;br /&gt;
      {&amp;quot;TITLE&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;title&amp;quot;]},&lt;br /&gt;
      {&amp;quot;URL&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;wWWHomePage&amp;quot;]},&lt;br /&gt;
      {&amp;quot;DESC&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;description&amp;quot;]},&lt;br /&gt;
      {&amp;quot;TEL&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;telephoneNumber&amp;quot;]}]},&lt;br /&gt;
    {ldap_search_fields,&lt;br /&gt;
     [{&amp;quot;User&amp;quot;, &amp;quot;%u&amp;quot;},&lt;br /&gt;
      {&amp;quot;Name&amp;quot;, &amp;quot;givenName&amp;quot;},&lt;br /&gt;
      {&amp;quot;Family Name&amp;quot;, &amp;quot;sn&amp;quot;},&lt;br /&gt;
      {&amp;quot;Email&amp;quot;, &amp;quot;mail&amp;quot;},&lt;br /&gt;
      {&amp;quot;Company&amp;quot;, &amp;quot;company&amp;quot;},&lt;br /&gt;
      {&amp;quot;Department&amp;quot;, &amp;quot;department&amp;quot;},&lt;br /&gt;
      {&amp;quot;Role&amp;quot;, &amp;quot;title&amp;quot;},&lt;br /&gt;
      {&amp;quot;Description&amp;quot;, &amp;quot;description&amp;quot;},&lt;br /&gt;
      {&amp;quot;Phone&amp;quot;, &amp;quot;telephoneNumber&amp;quot;}]},&lt;br /&gt;
    {ldap_search_reported,&lt;br /&gt;
     [{&amp;quot;Full Name&amp;quot;, &amp;quot;FN&amp;quot;},&lt;br /&gt;
      {&amp;quot;Nickname&amp;quot;, &amp;quot;NICKNAME&amp;quot;},&lt;br /&gt;
      {&amp;quot;Email&amp;quot;, &amp;quot;EMAIL&amp;quot;}]}&lt;br /&gt;
  ]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===模块配置===&lt;br /&gt;
&lt;br /&gt;
选项 modules 定义ejabberd启动后将被装载的模块的列表. 列表中的每个条目是一个组，第一个元素是一个模块的名称，第二个是一个模块列表的选项.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{modules, [ {ModuleName, ModuleOptions}, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 在这个例子里只有模块 mod_echo 被装载宁且没有在方括号内定义该模块的选项:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        {mod_echo,      []}&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在第二个例子里不带选项地装载了模块 mod_echo, mod_time, 和 mod_version. 特别注意, 除了最后一个条目, 所有条目都以一个逗号结尾:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        {mod_echo,      []},&lt;br /&gt;
        {mod_time,      []},&lt;br /&gt;
        {mod_version,   []}&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====模块一览====&lt;br /&gt;
&lt;br /&gt;
下表列出ejabberd里的所有模块.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!模块 !!功能	!!依赖&lt;br /&gt;
|-&lt;br /&gt;
|mod_adhoc	||特定命令 ([http://xmpp.org/extensions/xep-0050.html XEP-0050])	|| &lt;br /&gt;
|-&lt;br /&gt;
|mod_announce	||管理公告	||推荐 mod_adhoc&lt;br /&gt;
|-&lt;br /&gt;
|mod_caps	||实体能力 ([http://xmpp.org/extensions/xep-0115.html XEP-0115])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_configure	||使用特定命令配置服务器	||mod_adhoc&lt;br /&gt;
|-&lt;br /&gt;
|mod_disco	||服务发现 ([[XEP-0030]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_echo	||XMPP节回音	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_irc	        ||IRC网关	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_last	||最后活动 ([http://xmpp.org/extensions/xep-0012.html XEP-0012])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_last_odbc	||最后活动 ([http://xmpp.org/extensions/xep-0012.html XEP-0012])	||支持的数据库 (*)&lt;br /&gt;
|-&lt;br /&gt;
|mod_muc	||多用户聊天 ([[XEP-0045]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_muc_log	||多用户聊天室记录	||mod_muc&lt;br /&gt;
|-&lt;br /&gt;
|mod_offline	||离线消息存储 ([http://xmpp.org/extensions/xep-0160.html XEP-0160])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_offline_odbc	||离线消息存储 ([http://xmpp.org/extensions/xep-0160.html XEP-0160])	||支持的数据库 (*)&lt;br /&gt;
|-&lt;br /&gt;
|mod_ping	||XMPP Ping 和定期保持连接 ([http://xmpp.org/extensions/xep-0199.html XEP-0199])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_privacy	||禁止通讯 ([[RFC3921|XMPP IM]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_privacy_odbc	||禁止通讯 (([[RFC3921|XMPP IM]])	||支持的数据库 (*)&lt;br /&gt;
|-&lt;br /&gt;
|mod_private	||私有XML存储 ([http://xmpp.org/extensions/xep-0049.html XEP-0049])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_private_odbc	||私有XML存储 ([http://xmpp.org/extensions/xep-0049.html XEP-0049])	||支持的数据库 (*)&lt;br /&gt;
|-&lt;br /&gt;
|mod_proxy65	||SOCKS5字节流 ([[XEP-0065]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_pubsub	||发行-订阅 ([[XEP-0060]]), PEP ([[XEP-0163]])	||mod_caps&lt;br /&gt;
|-&lt;br /&gt;
|mod_pubsub_odbc	||发行-订阅 ([[XEP-0060]]), PEP ([[XEP-0163]])	||支持的数据库 (*) 和 mod_caps&lt;br /&gt;
|-&lt;br /&gt;
|mod_register	||I带内注册 ([[XEP-0077]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_roster	||名册管理 ([[RFC3921|XMPP IM]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_roster_odbc	||名册管理 ([[RFC3921|XMPP IM]])	||支持的数据库 (*)&lt;br /&gt;
|-&lt;br /&gt;
|mod_service_log	||拷贝用户消息到日志服务	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_shared_roster	||共享名册管理	||mod_roster 或	mod_roster_odbc&lt;br /&gt;
|-&lt;br /&gt;
|mod_sic	Server ||IP检查 ([[XEP-0279]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_stats	||统计信息收集 ([[XEP-0039]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_time	||实体时间 ([[XEP-0202]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_vcard	||电子名片 ([[XEP-0054]])	 ||&lt;br /&gt;
|-&lt;br /&gt;
|mod_vcard_ldap	||电子名片 ([[XEP-0054]])	||LDAP服务器&lt;br /&gt;
|-&lt;br /&gt;
|mod_vcard_odbc	||电子名片 ([[XEP-0054]])	||支持的数据库 (*)&lt;br /&gt;
|-&lt;br /&gt;
|mod_vcard_xupdate	||基于vCard的头像 ([[XEP-0153]])	||mod_vcard 或 mod_vcard_odbc&lt;br /&gt;
|-&lt;br /&gt;
|mod_version	||软件版本 ([[XEP-0092]])	 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* (*) 这个模块需要数据库支持. 关于支持的数据库列表, 见 [[Ejabberd2:安装和操作指南#数据库和LDAP配置|3.2]] 节. &lt;br /&gt;
&lt;br /&gt;
通过后缀你可以看到每个模块需要哪个数据库后端:&lt;br /&gt;
&lt;br /&gt;
* 没有后缀, 这意味着那个模块使用Erlang的内建数据库 Mnesia 作为后端.&lt;br /&gt;
* ‘_odbc’, 这意味着该模块需要一个支持的数据库 (见 [[Ejabberd2:安装和操作指南#数据库和LDAP配置|3.2]] 节) 作为后端.&lt;br /&gt;
* ‘_ldap’, 这意味着该模块需要一个LDAP服务器作为后端. &lt;br /&gt;
&lt;br /&gt;
如果你想要, 有可能使用一个关系数据库来存储信息件. 你可以通过在ejabberd 配置文件修改模块名称带上_odbc 后缀来实现这点. 你可以为以下数据使用关系数据库:&lt;br /&gt;
&lt;br /&gt;
* 最后连接日期和时间: 使用 mod_last_odbc 取代 mod_last.&lt;br /&gt;
* 离线消息: 使用 mod_offline_odbc 取代 mod_offline.&lt;br /&gt;
* 名册: 使用 mod_roster_odbc 取代 mod_roster.&lt;br /&gt;
* 用户的VCARD: 使用 mod_vcard_odbc 取代 mod_vcard.&lt;br /&gt;
* 私有XML存储: 使用 mod_private_odbc 取代 mod_private.&lt;br /&gt;
* 用户黑名单规则: 使用 mod_privacy_odbc 取代 mod_privacy. &lt;br /&gt;
&lt;br /&gt;
你可以在ejabberd网站找到更多别人[http://www.ejabberd.im/contributions 捐献的模块]的信息. 请记住这些捐献可能不能用或它们有些bug和安全泄露. 所以, 使用他们是你们自己的风险!&lt;br /&gt;
&lt;br /&gt;
====通用选项====&lt;br /&gt;
&lt;br /&gt;
以下选项被多个模块使用. 所以, 它们被单列一节.&lt;br /&gt;
&lt;br /&gt;
=====iqdisc=====&lt;br /&gt;
&lt;br /&gt;
很多模块为处理发到这个服务器或一个用户(例如. 给 example.org 或给 user@example.org)的不同namespaces的IQ queries定义了处理程序. 这个选项定义了这些queries的处理原则.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Value}'''&lt;br /&gt;
&lt;br /&gt;
可能的值有:&lt;br /&gt;
&lt;br /&gt;
'''no_queue'''&lt;br /&gt;
:一个拥有此处理原则的 namespace 的所有 queries 会被立即处理. 这也意味着在这个包完全处理完之前，不可以处理任何包. 如果一个query的处理可能消耗比较长的时间，今后将不推荐这个原则. &lt;br /&gt;
'''one_queue'''&lt;br /&gt;
:在这种情况下，将为一个拥有此处理原则的 namespace建立一个独立的队列来处理它们. 另外, 这个队列的处理和其他包的队列是并行的. 这个原则是最推荐的. &lt;br /&gt;
'''{queues, N}'''&lt;br /&gt;
:N个独立的队列被建立用来处理这些 queries. 因而 queries 被并行处理, 但是以一个可控的方法. &lt;br /&gt;
'''parallel'''&lt;br /&gt;
:对每一个拥有此原则的包产生一个独立的Erlang进程. 所以, 所有这些包被并行处理. 尽管Erlang进程的产生成本相对较低, 这可能中断服务器的正常工作, 因为Erlang模拟器对进程数量有限制 (缺省为32000). &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_time, [{iqdisc, no_queue}]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====host=====&lt;br /&gt;
&lt;br /&gt;
这个选项定义一个ejabberd 模块提供的服务的 Jabber ID.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{host, HostName}'''&lt;br /&gt;
&lt;br /&gt;
如果你在 HostName 里包含了关键字 &amp;quot;@HOST@&amp;quot; , 它在启动时被替换为真实的虚拟主机字符串.&lt;br /&gt;
&lt;br /&gt;
这个例子配置了 echo 模块以 Jabber ID mirror.example.org来提供它的回音服务:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_echo, [{host, &amp;quot;mirror.example.org&amp;quot;}]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
无论如何, 如果有多个虚拟主机并且这个模块在所有虚拟主机中都被激活, 必须使用&amp;quot;@HOST@&amp;quot; 关键字:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_echo, [{host, &amp;quot;mirror.@HOST@&amp;quot;}]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_announce====&lt;br /&gt;
&lt;br /&gt;
本模块允许配置用户广播公告并设定本日消息 (MOTD). 被配置的用户可以在一个XMPP客户端使用Ad-hoc命令或发送消息给指定的JIDs来执行这些动作.&lt;br /&gt;
&lt;br /&gt;
特定命令被列于服务发现. 要使用此功能, 必须激活 mod_adhoc 模块.&lt;br /&gt;
&lt;br /&gt;
可以发送消息的特定 JIDs 清单如下. 在每个条目的第一个 JID 将只应用于指定的虚拟主机 example.org, 而括号里的 JID 将应用于ejabberd的所有虚拟主机.&lt;br /&gt;
&lt;br /&gt;
'''example.org/announce/all (example.org/announce/all-hosts/all)'''&lt;br /&gt;
:消息将被发送给所有注册用户. 如果用户在线并连接了多个资源, 只有高优先级的资源将收到消息. 如果注册用户没有连接, 消息将离线存储，假定激活了离线存储 (见  [[Ejabberd2:安装和操作指南#mod_offline|3.3.12] 节). &lt;br /&gt;
'''example.org/announce/online (example.org/announce/all-hosts/online)'''&lt;br /&gt;
:消息被发送到所有已连接的用户. 如果用户在线且连接了多个资源, 所有资源将接收到消息. &lt;br /&gt;
'''example.org/announce/motd (example.org/announce/all-hosts/motd)'''&lt;br /&gt;
:该消息被设置为每日消息 (MOTD) 并在用户登录时被发送给用户. 另外这个消息会被发送给所有连接的用户 (类似 announce/online). &lt;br /&gt;
'''example.org/announce/motd/update (example.org/announce/all-hosts/motd/update)'''&lt;br /&gt;
:该消息被设置为每日消息 (MOTD) 并在用户登录时被发送给用户. 这个消息不发送给任何当前已连接的用户. &lt;br /&gt;
'''example.org/announce/motd/delete (example.org/announce/all-hosts/motd/delete)'''&lt;br /&gt;
:任何发送到此JID的消息移除现有的每日消息 (MOTD). &lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{access, AccessName}'''&lt;br /&gt;
:这个选项指定谁被允许发送公告并设置每日消息 (缺省的, 没有人能发送这类消息). &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 只有管理员能发送公告:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {access, announce, [{allow, admins}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_adhoc, []},&lt;br /&gt;
        {mod_announce, [{access, announce}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 管理员以及 direction 可发送公告:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, direction, {user, &amp;quot;big_boss&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {acl, direction, {user, &amp;quot;assistant&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {acl, admins, {user, &amp;quot;admin&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
      {access, announce, [{allow, admins},&lt;br /&gt;
                          {allow, direction}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_adhoc, []},&lt;br /&gt;
        {mod_announce, [{access, announce}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
注意 mod_announce 在大的布署里可能是资源敏感的，因为它可能广播非常多的消息. 对于拥有成百上千用户的ejabberd实例，这个模块应该被禁止.&lt;br /&gt;
&lt;br /&gt;
====mod_disco====&lt;br /&gt;
&lt;br /&gt;
这个模块增加多服务发现 ([[XEP-0030]]) 的支持. 激活本模块, 你的服务器上的服务可以被XMPP客户端发现. 注意ejabberd没有模块支持被取代的 Jabber Browsing ([http://xmpp.org/extensions/xep-0011.html XEP-0011]) 和 Agent Information ([http://xmpp.org/extensions/xep-0094.html XEP-0094]). 于是,如果你想它们能发现你提供的服务，XMPP客户端需要支持这个比较新的发现协议.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这定义服务发现的IQ queries的处理原则 (http://jabber.org/protocol/disco#items 和 http://jabber.org/protocol/disco#info)  (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]]). &lt;br /&gt;
'''{extra_domains, [Domain, ...]}'''&lt;br /&gt;
:使用这个选项, 你可以指定一个增加到服务发现条目列表中的附加域的列表. &lt;br /&gt;
'''{server_info, [ {Modules, Field, [Value, ...]}, ... ]}'''&lt;br /&gt;
:指定关于本服务器的额外的信息, 参见 XMPP服务的联系地址 ([http://xmpp.org/extensions/xep-0157.html XEP-0157]). Modules 可以是关键字‘all’, 这种情况下信息被汇报给所有服务; 或是一个 ejabberd 模块的列表, 这种情况下信息仅被指定给那些模块提供的服务. 可以指定任意的 Field 和 Value , 不只是联系地址. &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 提供一个链接到jabber.org上的Jabber用户目录:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_disco, [{extra_domains, [&amp;quot;users.jabber.org&amp;quot;]}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 提供一个链接到其他服务器的网关:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_disco, [{extra_domains, [&amp;quot;icq.example.com&amp;quot;,&lt;br /&gt;
                                      &amp;quot;msn.example.com&amp;quot;]}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 提供一个链接到一些友好的服务器:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_disco, [{extra_domains, [&amp;quot;example.org&amp;quot;,&lt;br /&gt;
                                      &amp;quot;example.com&amp;quot;]}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 使用这个配置, 所有服务在主服务器显示滥用地址, 回复地址, 并同时在主服务器和vJUD服务显示管理员地址:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_disco, [{server_info, [&lt;br /&gt;
            {all,&lt;br /&gt;
             &amp;quot;abuse-addresses&amp;quot;,&lt;br /&gt;
             [&amp;quot;mailto:abuse@shakespeare.lit&amp;quot;]},&lt;br /&gt;
            {[mod_muc],&lt;br /&gt;
             &amp;quot;Web chatroom logs&amp;quot;,&lt;br /&gt;
             [&amp;quot;http://www.example.org/muc-logs&amp;quot;]},&lt;br /&gt;
            {[mod_disco],&lt;br /&gt;
             &amp;quot;feedback-addresses&amp;quot;,&lt;br /&gt;
             [&amp;quot;http://shakespeare.lit/feedback.php&amp;quot;, &amp;quot;mailto:feedback@shakespeare.lit&amp;quot;, &amp;quot;xmpp:feedback@shakespeare.lit&amp;quot;]},&lt;br /&gt;
            {[mod_disco, mod_vcard],&lt;br /&gt;
             &amp;quot;admin-addresses&amp;quot;,&lt;br /&gt;
             [&amp;quot;mailto:xmpp@shakespeare.lit&amp;quot;, &amp;quot;xmpp:admins@shakespeare.lit&amp;quot;]}&lt;br /&gt;
        ]}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_echo====&lt;br /&gt;
&lt;br /&gt;
本模块简单地对任何XMPP包发出回音给发送者. ejabberd和XMPP客户端调试可能对这个镜子感兴趣.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{host, HostName}'''&lt;br /&gt;
:这个选项定义服务的Jabber ID. 如果 host 选项没指定, Jabber ID 将是前缀‘echo.’加该虚拟主机的 hostname . 关键字 &amp;quot;@HOST@&amp;quot; 在启动时被替换成真实的虚拟主机名. &lt;br /&gt;
&lt;br /&gt;
例子: 镜子, 镜子, 在墙上, 他们谁是最美丽的?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_echo, [{host, &amp;quot;mirror.example.org&amp;quot;}]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_http_bind====&lt;br /&gt;
&lt;br /&gt;
本模块实现了定义于 [http://xmpp.org/extensions/xep-0124.html XEP-0124] 和 [http://xmpp.org/extensions/xep-0206.html XEP-0206]的 XMPP over Bosh (正式的名字是 HTTP Binding). 它在这个将被伺服的服务上以一个可配置的资源扩展了ejabberd的HTTP服务， .&lt;br /&gt;
&lt;br /&gt;
要使用 HTTP-Binding, 激活这个模块:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_http_bind, []},&lt;br /&gt;
  ...&lt;br /&gt;
]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并增加 http_bind 到 HTTP 服务. 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{listen, &lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {5280, ejabberd_http, [&lt;br /&gt;
                         http_bind,&lt;br /&gt;
                         http_poll,&lt;br /&gt;
                         web_admin&lt;br /&gt;
                        ]&lt;br /&gt;
  },&lt;br /&gt;
  ...&lt;br /&gt;
]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
使用这个配置, module 将伺服发送给 http://example.org:5280/http-bind/ 的请求. 记住这个页面不是被设计给web浏览器使用的, 它是被支持XMPP over Bosh的XMPP客户端使用的.&lt;br /&gt;
&lt;br /&gt;
如果你想以不同的URI路径设置服务或使用一个不同的模块, 你可以使用选项request_handlers手工配置它. 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{listen, &lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {5280, ejabberd_http, [&lt;br /&gt;
                         {request_handlers, [{[&amp;quot;http-bind&amp;quot;], mod_http_bind}]},&lt;br /&gt;
                         http_poll,&lt;br /&gt;
                         web_admin&lt;br /&gt;
                        ]&lt;br /&gt;
  },&lt;br /&gt;
  ...&lt;br /&gt;
]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{max_inactivity, Seconds}'''&lt;br /&gt;
:以秒数定义最大闲置时间. 缺省值为30秒. 例如, 设置成50秒:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    {modules,&lt;br /&gt;
     [&lt;br /&gt;
      ...&lt;br /&gt;
      {mod_http_bind, [ {max_inactivity, 50} ]},&lt;br /&gt;
      ...&lt;br /&gt;
    ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_http_fileserver====&lt;br /&gt;
&lt;br /&gt;
这个简单的模块从本地磁盘通过HTTP提供文件服务.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{docroot, Path}'''&lt;br /&gt;
:伺服文件的目录. &lt;br /&gt;
'''{accesslog, Path}'''&lt;br /&gt;
:使用一个类似Apache格式的日志文件. 如果没指定本选项则不记录日志. &lt;br /&gt;
'''{directory_indices, [Index, ...]}'''&lt;br /&gt;
:包含一个或多个目录的索引文件, 类似 Apache的 DirectoryIndex 变量. 当一个web请求去到一个目录而不是常规的文件, 那些目录的 indices 被顺序装载, 并且返回被发现的第一个. &lt;br /&gt;
'''{custom_headers, [ {Name, Value}, ...]}'''&lt;br /&gt;
:表明自定义的HTTP头将被包含在所有应答中. 缺省值是: [] &lt;br /&gt;
'''{content_types, [ {Name, Type}, ...]}'''&lt;br /&gt;
:指定内容类型的扩展. 已经定义了很多 content types , 使用本选项你可以增加新的定义, 修改或删除现存的. 要删除现有定义, 简单的以一个值定义它: ‘undefined’. &lt;br /&gt;
'''{default_content_type, Type}'''&lt;br /&gt;
:指定 content type 使用未知的扩展. 缺省是‘application/octet-stream’. &lt;br /&gt;
&lt;br /&gt;
这个实例配置将从本地目录 /var/www 在地址 http://example.org:5280/pub/archive/ 提供文件服务. 在这个例子定义了一个新的 content type ogg, png 重新定义了, 而 jpg 定义被删除了. 要使用本模块你必须激活它:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_http_fileserver, [&lt;br /&gt;
                         {docroot, &amp;quot;/var/www&amp;quot;}, &lt;br /&gt;
                         {accesslog, &amp;quot;/var/log/ejabberd/access.log&amp;quot;},&lt;br /&gt;
                         {directory_indices, [&amp;quot;index.html&amp;quot;, &amp;quot;main.htm&amp;quot;]},&lt;br /&gt;
                         {custom_headers, [{&amp;quot;X-Powered-By&amp;quot;, &amp;quot;Erlang/OTP&amp;quot;},&lt;br /&gt;
                                           {&amp;quot;X-Fry&amp;quot;, &amp;quot;It's a widely-believed fact!&amp;quot;}&lt;br /&gt;
                                          ]},&lt;br /&gt;
                         {content_types, [{&amp;quot;.ogg&amp;quot;, &amp;quot;audio/ogg&amp;quot;},&lt;br /&gt;
                                          {&amp;quot;.png&amp;quot;, &amp;quot;image/png&amp;quot;},&lt;br /&gt;
                                          {&amp;quot;.jpg&amp;quot;, undefined}&lt;br /&gt;
                                         ]},&lt;br /&gt;
                         {default_content_type, &amp;quot;text/html&amp;quot;}&lt;br /&gt;
                        ]&lt;br /&gt;
  },&lt;br /&gt;
  ...&lt;br /&gt;
]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并且在HTTP服务里把它定义为一个处理器:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{listen, &lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {5280, ejabberd_http, [&lt;br /&gt;
                         ...&lt;br /&gt;
                         {request_handlers, [&lt;br /&gt;
                                             ...&lt;br /&gt;
                                             {[&amp;quot;pub&amp;quot;, &amp;quot;archive&amp;quot;], mod_http_fileserver},&lt;br /&gt;
                                             ...&lt;br /&gt;
                                            ]&lt;br /&gt;
                         },&lt;br /&gt;
                         ...&lt;br /&gt;
                        ]&lt;br /&gt;
  },&lt;br /&gt;
  ...&lt;br /&gt;
]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_irc====&lt;br /&gt;
&lt;br /&gt;
本模块是一个 IRC 网关用于加入IRC服务器的频道.&lt;br /&gt;
&lt;br /&gt;
最终用户信息:&lt;br /&gt;
&lt;br /&gt;
* 一个支持‘groupchat 1.0’或 Multi-User Chat ([[XEP-0045]])的XMPP客户端需要加入IRC频道.&lt;br /&gt;
* 一个IRC频道可能被以近似相同的方式加入一个XMPP多用户聊天室. 不同处是房间名将变成‘channel%irc.example.org’，在这个情况下 irc.example.org 是伺服‘channel’的IRC服务器. 并且当然这个主机应该指向IRC网关而不是多用户聊天服务.&lt;br /&gt;
* 你可以注册你的昵称，通过发送‘IDENTIFY password’到 nickserver!irc.example.org@irc.jabberserver.org.&lt;br /&gt;
* 键入你的密码，通过发送‘LOGIN nick password’到 nickserver!irc.example.org@irc.jabberserver.org.&lt;br /&gt;
* IRC网关提供 Ad-Hoc Commands ([http://xmpp.org/extensions/xep-0050.html XEP-0050]) 来加入一个频道, 并设定自定义的 IRC 用户名和编码.&lt;br /&gt;
* 当使用一个流行的XMPP服务器, 可能它没有到一些IRC服务器的连接存在，因为它们限制从一个IP来的连接的数量. &lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{host, HostName}'''&lt;br /&gt;
:这个选项定义该服务的 Jabber ID. 如果 host 选项未定义, Jabber ID 将是该虚拟主机的 hostname 加上前缀‘irc.’. 关键字 &amp;quot;@HOST@&amp;quot; 在启动时被替换成真实的虚拟主机名. &lt;br /&gt;
'''{access, AccessName}'''&lt;br /&gt;
:这个选项可被用于定义谁能使用 IRC 网关 (缺省值: all). &lt;br /&gt;
'''{default_encoding, Encoding}'''&lt;br /&gt;
:设置缺省的 IRC 编码. 缺省值: &amp;quot;koi8-r&amp;quot; &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 在第一个例子里, IRC网关在你的所有带有前缀‘irc.’的虚拟主机上可用. 进一步的, 任何人可以使用这个这个网关. 缺省编码设为 &amp;quot;iso8859-15&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_irc, [{access, all}, {default_encoding, &amp;quot;iso8859-15&amp;quot;}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在下一个例子，IRC网关对于那些拥有前缀irc-t.net的JIDs可用. 而且, 这个网关只可以被example.org的两个用户以及example.com上的所有用户使用:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, paying_customers, {user, &amp;quot;customer1&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {acl, paying_customers, {user, &amp;quot;customer2&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {acl, paying_customers, {server, &amp;quot;example.com&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
      {access, irc_users, [{allow, paying_customers}, {deny, all}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_irc, [{access, irc_users},&lt;br /&gt;
                   {host, &amp;quot;irc.example.net&amp;quot;}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_last====&lt;br /&gt;
&lt;br /&gt;
本模块增加对最后活动([http://xmpp.org/extensions/xep-0012.html XEP-0012])的支持. 它可被用于发现什么时候离线用户最后一次访问服务器, 并知道在这台服务器上一个连接的用户的最后活动, 或查询ejabberd服务器的运行时间.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这是为 最后活动(jabber:iq:last) IQ queries 定义处理原则(见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节).&lt;br /&gt;
&lt;br /&gt;
====mod_muc====&lt;br /&gt;
&lt;br /&gt;
本模块提供一个多用户聊天([[XEP-0045]])服务. 用户可以发现现有房间, 加入或新建房间. 房间的房客可以公开或私下聊天.&lt;br /&gt;
&lt;br /&gt;
多用户聊天的一些功能:&lt;br /&gt;
&lt;br /&gt;
* 发送公开或私有消息给房间房客.&lt;br /&gt;
* 邀请其他用户到一个房间.&lt;br /&gt;
* 设定一个房间的标题.&lt;br /&gt;
* 建立密码保护房间.&lt;br /&gt;
* 踢人或拉黑名单. &lt;br /&gt;
&lt;br /&gt;
这个MUC服务允许任何Jabber ID注册一个昵称, 这样没有别人可以在该MUC服务的任何房间使用那个昵称. 为了注册一个昵称, 在你的XMPP客户端打开服务发现并注册到该MUC服务.&lt;br /&gt;
&lt;br /&gt;
本模块支持集群和负载均衡. 一个模块可被每个集群节点启动. 在特定的时间房间分布于所有可用的MUC模块实例上. 多用户聊天模块是集群的但房间本身不是集群的，也不是容错的: 如果管理那些房间的节点挂了, 那些房间就消失了并且它们将在第一次尝试连接得到的可用节点上重建.&lt;br /&gt;
&lt;br /&gt;
Module 选项:&lt;br /&gt;
&lt;br /&gt;
'''{host, HostName}'''&lt;br /&gt;
:这个选项定义服务的Jabber ID. 如果 host 选项未指定, 该Jabber ID将是虚拟主机的hostname加上前缀‘conference.’. 关键字 &amp;quot;@HOST@&amp;quot; 在启动时被替换为真实的虚拟主机名. &lt;br /&gt;
'''{access, AccessName}'''&lt;br /&gt;
:你可以指定谁有权使用多用户聊天服务. 缺省每个人都被允许使用它. &lt;br /&gt;
'''{access_create, AccessName}'''&lt;br /&gt;
:为配置在多用户聊天服务里谁被允许创建新房间 , 可使用这个选项. 缺省任何本地ejabberd服务器的帐号都被允许新建房间. &lt;br /&gt;
'''{access_persistent, AccessName}'''&lt;br /&gt;
:为配置谁被允许修改持久 ’persistent’房间的选项. 缺省任何本地ejabberd服务器的帐号被允许修改那个选项. &lt;br /&gt;
'''{access_admin, AccessName}'''&lt;br /&gt;
:这个选项指定谁被允许管理多用户聊天服务. 缺省值为 none, 它意味着只有房间创建者可以管理他的房间. 管理员们可以发送一个普通消息给服务 JID, 并且它将被作为一个服务消息显示在所有房间. 管理员们可以发送一个 groupchat 消息给一个激活的房间的JID, 并且该消息将被显示为一个服务消息. &lt;br /&gt;
'''{history_size, Size}'''&lt;br /&gt;
:当用户进入房间时被发送给用户的一个当前讨论的短小历史. 使用此选项你可以定义保持的历史数据数量，用来在用户加入房间时发送给他们. 这个值是一个整数. 设定这个值为 0 禁止历史功能并且, 导致一个结果, 没东西保留在内存里. 这个缺省值是 20. 这个值是全局的并且因而会影响服务的所有房间. &lt;br /&gt;
'''{max_users, Number}'''&lt;br /&gt;
:这个选项定义是服务级别的, 每房间允许的最大用户数. 它可以低于每个房间的配置但是不能在单个的房间配置里增加. 缺省值为200. &lt;br /&gt;
'''{max_users_admin_threshold, Number}'''&lt;br /&gt;
:这个选项定义，当房间允许的最大房客数量达到之后，被允许进入房间的服务管理员或房间所有者的数量. 缺省限制为 5. &lt;br /&gt;
'''{max_user_conferences, Number}'''&lt;br /&gt;
:这个选项定义给定用户能加入的房间的最大数量. 缺省值为 10. 这个选项被用于阻止可能的滥用. 注意这是个软限制: 一些用户有时候可以在集群配置里加入更多的会议. &lt;br /&gt;
'''{max_room_id, Number}'''&lt;br /&gt;
:这个选项定义,当新建一个房间时,Room ID 字符串的可以有的最大长度. 缺省值是不限制: infinite. &lt;br /&gt;
'''{max_room_name, Number}'''&lt;br /&gt;
:这个选项定义,当配置一个房间时,Room Name 字符串的可以有的最大长度. 缺省值是不限制: infinite. &lt;br /&gt;
'''{max_room_desc, Number}'''&lt;br /&gt;
:这个选项定义,当配置一个房间时,Room Description 字符串的可以有的最大长度. 缺省值是不限制: infinite.     &lt;br /&gt;
'''{min_message_interval, Number}'''&lt;br /&gt;
:这个选项定义,在一个房客发送的两个消息之间的最小间隔时间,以秒计. 这个选项是全局的并且检查所有房间. 可使用一个十进制值. 当这个选项没定义时, 消息速率是不限制的. 这个功能可用来保护MUC服务不被房客滥用并限制服务广播的消息数量. 对于这个最小消息间隔时间,一个比较好的值是0.4秒. 如果一个房客试图更快地发送消息, 发回一个错误并解释这个消息已被抛弃并描述为什么消息不被接受的原因. &lt;br /&gt;
'''{min_presence_interval, Number}'''&lt;br /&gt;
:这个选项定义一个给定房客的两次出席信息变更之间的最小时间，以秒计. 这个选项是全局的并且会对所有房间生效. 可以用一个十进制数值. 当这个选项没有定义的时候, 没有限制. 这个选项可被用于保护一个MUC服务不被房客滥用. 如果一个房客试图在指定的间隔时间内更多次的变更出席信息, 这个出席信息被 ejabberd 缓存并只有在间隔延迟过期后最新的出席信息被广播给房间里的所有房客. 中间的出席信息包被安静的抛弃. 一个好的选项值是4秒. &lt;br /&gt;
'''{default_room_options, [ {OptionName, OptionValue}, ...]}'''&lt;br /&gt;
:这个选项允许定义期望的缺省房间选项. 注意一个房间的创建者可以在任何时候使用一个有MUC能力的XMPP客户端修改他自己的房间的选项. 可用的房间选项和缺省值有:&lt;br /&gt;
&lt;br /&gt;
:    '''{allow_change_subj, true|false}'''&lt;br /&gt;
::允许房客修改标题. &lt;br /&gt;
:    '''{allow_private_messages, true|false}'''&lt;br /&gt;
::房客可以发送私有消息给其他房客. &lt;br /&gt;
:    '''{allow_query_users, true|false}'''&lt;br /&gt;
::房客可发送 IQ queries 给其他房客. &lt;br /&gt;
:    '''{allow_user_invites, false|true}'''&lt;br /&gt;
::允许房客发送邀请. &lt;br /&gt;
:    '''{allow_visitor_nickchange, true|false}'''&lt;br /&gt;
::允许游客修改昵称. &lt;br /&gt;
:    '''{allow_visitor_status, true|false}'''&lt;br /&gt;
::允许游客在出席信息更新里发送status状态文本. I如果不允许, 在广播出席信息更新给房间里所有的房客时这个 status 文本被剥离. &lt;br /&gt;
:    '''{anonymous, true|false}'''&lt;br /&gt;
::这个房间是匿名的: 房客看不到其他房客的真实JIDs. 注意房间主持人们总是看得见房客的真实JIDs. &lt;br /&gt;
:    '''{logging, false|true}'''&lt;br /&gt;
::公开消息被使用mod_muc_log记录. &lt;br /&gt;
:    '''{max_users, 200}'''&lt;br /&gt;
::房间里房客的最大数量. &lt;br /&gt;
:    '''{members_by_default, true|false}'''&lt;br /&gt;
::进入房间的房客缺省成为参与者, 所以他们有发言权 ’voice’. &lt;br /&gt;
:    '''{members_only, false|true}'''&lt;br /&gt;
::只有房间成员可以进入. &lt;br /&gt;
:    '''{moderated, true|false}'''&lt;br /&gt;
::只有拥有发言权 ’voice’的房客可以发送公开消息. &lt;br /&gt;
:    '''{password, &amp;quot;roompass123&amp;quot;}'''&lt;br /&gt;
::房间密码. 你可能希望也激活下一个选项. &lt;br /&gt;
:    '''{password_protected, false|true}'''&lt;br /&gt;
::要求密码才能进入房间. &lt;br /&gt;
:    '''{persistent, false|true}'''&lt;br /&gt;
::即使最后一个房客离开，房间仍持久存在. &lt;br /&gt;
:    '''{public, true|false}'''&lt;br /&gt;
::房间在MUC服务列表里是公开的, 所以它是可发现的. &lt;br /&gt;
:    '''{public_list, true|false}'''&lt;br /&gt;
::参与者名单是公开的, 不需要进入房间就能拿到. &lt;br /&gt;
:    '''{title, &amp;quot;Room Title&amp;quot;}'''&lt;br /&gt;
::一个自然语言的房间称谓. &lt;br /&gt;
&lt;br /&gt;
:所有房间选项能被设定为 true 或 false, 除了 password 和 title 是字符串, 以及 max_users 是整数. &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 在第一个例子里，每个人都允许使用多用户聊天服务. 每个人也将能创建房间但只有用户admin@example.org被允许管理任何房间. 在这个例子里他也是一个全局的管理员. 当admin@example.org发送一个消息，例如‘Tomorrow, the XMPP server will be moved to new hardware. This will involve service breakdowns around 23:00 UMT. We apologise for this inconvenience.’ 给 conference.example.org, 这个消息将被显示在所有激活的房间里. 在这个例子里历史功能被禁止了.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, admin, {user, &amp;quot;admin&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
      {access, muc_admin, [{allow, admin}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_muc, [{access, all},&lt;br /&gt;
                   {access_create, all},&lt;br /&gt;
                   {access_admin, muc_admin},&lt;br /&gt;
                   {history_size, 0}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在第二个例子里多用户聊天服务只允许在我们的域和其他的服务器上注册了的付费客户访问. 当然管理员也是允许访问房间的. 而且, 他是唯一被授权可以建立并管理房间的. 当admin@example.org发送一个消息，例如‘Tomorrow, the Jabber server will be moved to new hardware. This will involve service breakdowns around 23:00 UMT. We apologise for this inconvenience.’ 给 conference.example.org, 它将被显示在所有激活的房间里. 没有使用 history_size 选项, 这意味着这个功能被激活但缺省值为20个历史消息，将被发送给用户们.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, paying_customers, {user, &amp;quot;customer1&amp;quot;, &amp;quot;example.net&amp;quot;}}.&lt;br /&gt;
      {acl, paying_customers, {user, &amp;quot;customer2&amp;quot;, &amp;quot;example.com&amp;quot;}}.&lt;br /&gt;
      {acl, paying_customers, {user, &amp;quot;customer3&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {acl, admin, {user, &amp;quot;admin&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
      {access, muc_admin, [{allow, admin},&lt;br /&gt;
                            {deny, all}]}.&lt;br /&gt;
      {access, muc_access, [{allow, paying_customers},&lt;br /&gt;
                            {allow, admin},&lt;br /&gt;
                            {deny, all}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_muc, [{access, muc_access},&lt;br /&gt;
                   {access_create, muc_admin},&lt;br /&gt;
                   {access_admin, muc_admin}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在以下例子里, MUC使用了反滥用选项. 一个房客每0.4秒不能发送超过一个消息并且不能超过每4秒之内变更一次出席信息. Room IDs 和 Room Names 的长度被限制为 20 个字符, 而 Room Description 限制为 300 个字符. 没有定义 ACLs, 但一些用户限制可能被加入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_muc, [{min_message_interval, 0.4},&lt;br /&gt;
                   {min_presence_interval, 4},&lt;br /&gt;
                   {max_room_id, 20},&lt;br /&gt;
                   {max_room_name, 20},&lt;br /&gt;
                   {max_room_desc, 300}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 这个例子展示如何使用 default_room_options 来确保新建房间缺省拥有的选项.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_muc, [{access, muc_access},&lt;br /&gt;
                   {access_create, muc_admin},&lt;br /&gt;
                   {default_room_options,&lt;br /&gt;
                    [&lt;br /&gt;
                     {allow_change_subj, false},&lt;br /&gt;
                     {allow_query_users, true},&lt;br /&gt;
                     {allow_private_messages, true},&lt;br /&gt;
                     {members_by_default, false},&lt;br /&gt;
                     {title, &amp;quot;New chatroom&amp;quot;},&lt;br /&gt;
                     {anonymous, false}&lt;br /&gt;
                    ]},&lt;br /&gt;
                   {access_admin, muc_admin}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_muc_log====&lt;br /&gt;
&lt;br /&gt;
本模块允许可选的把多用户聊天 (MUC)的公开谈话记录转为HTML. 一旦你激活了这个模块, 用户可以使用有MUC能力的XMPP客户端加入一个房间, 并且如果他们有足够的权限, 他们可以请求一个配置表单来设定配置并允许房间记录.&lt;br /&gt;
&lt;br /&gt;
功能:&lt;br /&gt;
&lt;br /&gt;
* 每页顶端加上房间细节: room 称谓, JID, 作者, 标题以及配置.&lt;br /&gt;
* 房间JID 在生成的HTML里是一个链接，可用来加入该房间(使用 [http://xmpp.org/rfcs/rfc5122.html XMPP URI]).&lt;br /&gt;
* 标题和房间配置变更会被跟踪和显示.&lt;br /&gt;
* 加入, 离开, 修改昵称, 踢人, 拉黑名单和‘/me’被跟踪和显示, 包括原因(如果有).&lt;br /&gt;
* 生成的 HTML 文件是 XHTML 1.0 Transitional 和 CSS 兼容的.&lt;br /&gt;
* 时间戳是自参考的链接.&lt;br /&gt;
* 快速浏览的链接在顶上: 前一天, 下一天, 上.&lt;br /&gt;
* CSS被用于style定义, 可以使用一个自定义的 CSS 文件.&lt;br /&gt;
* 消息和标题里的URLs被转换为超链接.&lt;br /&gt;
* 时间戳上的时区被显示在记录文件里.&lt;br /&gt;
* 可在每一个页的顶部增加一个自定义链接. &lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{access_log, AccessName}'''&lt;br /&gt;
:这个选项限制哪个房客被允许激活和禁止房间记录. 缺省值为 muc_admin. 注意对于为了这个缺省设定生效，你需要有一个用于 muc_admin 的 access rule . &lt;br /&gt;
'''{cssfile, false|URL}'''&lt;br /&gt;
:使用这个选项你可以设置是否该HTML文件应该使用一个自定义的CSS文件或他们需要使用嵌入的CSS文件. 被允许的值有 false 和一个指向某CSS文件的URL. 使用第一个值, HTML文件将包含一个嵌入的CSS代码. 使用后一个, 你可以指定自定义CSS文件的URL (例如: &amp;quot;http://example.com/my.css&amp;quot;). 缺省的值是 false. &lt;br /&gt;
'''{dirname, room_jid|room_name}'''&lt;br /&gt;
:允许配置房间目录的名字. 被允许的值有 room_jid 和 room_name. 使用前者的值, 房间目录名将是完整的房间JID. 使用后者, 房间目录名将只是房间的名字, 不包括 MUC服务名. 缺省值是room_jid. &lt;br /&gt;
'''{dirtype, subdirs|plain}'''&lt;br /&gt;
:新建目录的类型可使用此选项指定. 允许的值有 subdirs 和 plain. 使用前者, 子目录以每年和月新建. 使用后者, 记录文件名包含完整的日期, 并且没有子目录. 缺省值是 subdirs. &lt;br /&gt;
'''{file_format, html|plaintext}'''&lt;br /&gt;
:定义日志文件的格式: html 存储成HTML格式, plaintext 存储成纯文本. 缺省值为 html. &lt;br /&gt;
'''{outdir, Path}'''&lt;br /&gt;
:这个选项是应该被存储的HTML文件的目录的全路径. 确保ejabberd守候进程对那个目录有写权限. 缺省值为 &amp;quot;www/muc&amp;quot;. &lt;br /&gt;
'''{spam_prevention true|false}'''&lt;br /&gt;
:为了阻止垃圾, spam_prevention 选项增加了一个特别的属性给链接来阻止它们通过搜索引擎来索引. 缺省值为 true, 它意味着 nofollow 属性将被加到用户提交的链接里. &lt;br /&gt;
'''{timezone, local|universal}'''&lt;br /&gt;
:记录的时区可使用本选项配置. 允许的值有 local 和 universal. 使用前者, 将使用Erlang通过操作系统获得的本地时间. 使用后者, 将使用GMT/UTC 时间. 缺省值为 local. &lt;br /&gt;
'''{top_link, {URL, Text}}'''&lt;br /&gt;
:使用本选项你可以定制化每个日志文件的右上角的链接. 缺省值是 {&amp;quot;/&amp;quot;, &amp;quot;Home&amp;quot;}. &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 在第一个例子里，任何房间所有者能激活记录, 并将使用一个自定义的CSS文件 (http://example.com/my.css). 记录文件的名字将包含完整日期, 并且将没有子目录. 记录文件将被存储在 /var/www/muclogs, 且时区将是GMT/UTC. 最后, 顶端链接将是 &amp;lt;a href=&amp;quot;http://www.jabber.ru/&amp;quot;&amp;gt;Jabber.ru&amp;lt;/a&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {access, muc, [{allow, all}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_muc_log, [&lt;br /&gt;
                       {access_log, muc},&lt;br /&gt;
                       {cssfile, &amp;quot;http://example.com/my.css&amp;quot;},&lt;br /&gt;
                       {dirtype, plain},&lt;br /&gt;
                       {dirname, room_jid},&lt;br /&gt;
                       {outdir, &amp;quot;/var/www/muclogs&amp;quot;},&lt;br /&gt;
                       {timezone, universal},&lt;br /&gt;
                       {spam_prevention, true},&lt;br /&gt;
                       {top_link, {&amp;quot;http://www.jabber.ru/&amp;quot;, &amp;quot;Jabber.ru&amp;quot;}}&lt;br /&gt;
                      ]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 在第二个例子里只有admin1@example.org和admin2@example.net可以激活记录, 并且将使用嵌入的CSS文件. 记录名将只包含日期(数字), 且每年和月将有子目录. 这个记录文件将被存储在 /var/www/muclogs, 且将使用本地时间. 最后, 顶端链接将是缺省的 &amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, admins, {user, &amp;quot;admin1&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {acl, admins, {user, &amp;quot;admin2&amp;quot;, &amp;quot;example.net&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
      {access, muc_log, [{allow, admins},&lt;br /&gt;
                         {deny, all}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_muc_log, [&lt;br /&gt;
                       {access_log, muc_log},&lt;br /&gt;
                       {cssfile, false},&lt;br /&gt;
                       {dirtype, subdirs},&lt;br /&gt;
                       {outdir, &amp;quot;/var/www/muclogs&amp;quot;},&lt;br /&gt;
                       {timezone, local}&lt;br /&gt;
                      ]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_offline====&lt;br /&gt;
&lt;br /&gt;
本模块实现离线消息存储 ([http://xmpp.org/extensions/xep-0160.html XEP-0160]). 这意味着所有被发送给一个离线用户的消息将被存储在服务器上直到那个用户再次上线. 所以它非常类似邮件的工作. 注意 ejabberdctl 有一个命令删除过期的消息 (见 [[Ejabberd2:安装和操作指南#ejabberdctl|4.1]] 节).&lt;br /&gt;
&lt;br /&gt;
'''{access_max_user_messages, AccessName}'''&lt;br /&gt;
:这个选项定义哪个 access rule 将被强迫用来限制一个用户所拥有的离线消息的最大数量(配额). 当一个用户有太多离线消息, 任何收到的新消息将被抛弃, 并且将返回一个 资源约束 错误给发送者. 缺省值为 max_user_offline_messages. 接着你可以用类似max_user_sessions的语法定义一个 access rule (见 [[Ejabberd2:安装和操作指南#用ACL限制打开的会话|3.1.5]] 节). &lt;br /&gt;
&lt;br /&gt;
这个例子允许强力用户拥有大到 5000 个离线消息, 管理员达到 2000, 所有其他用户达到 100.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{acl, admin, {user, &amp;quot;admin1&amp;quot;, &amp;quot;localhost&amp;quot;}}.&lt;br /&gt;
{acl, admin, {user, &amp;quot;admin2&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
{acl, poweruser, {user, &amp;quot;bob&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
{acl, poweruser, {user, &amp;quot;jane&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
{access, max_user_offline_messages, [ {5000, poweruser}, {2000, admin}, {100, all} ]}.&lt;br /&gt;
&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_offline,  [ {access_max_user_messages, max_user_offline_messages} ]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_ping====&lt;br /&gt;
&lt;br /&gt;
这个模块实现对XMPP Ping ([[XEP-0199]]) 和 定期保持连接 的支持. 当本模块激活时，ejabberd正确应答 ping 请求, 如协议所述.&lt;br /&gt;
&lt;br /&gt;
配置选项:&lt;br /&gt;
&lt;br /&gt;
'''{send_pings, true|false}'''&lt;br /&gt;
:如果这个选项设为 true, 服务器在一个给定的间隔时间 ping_interval发送 pings 给已连接的不活跃的客户端. 这对于保持活着的客户端连接或检查可用性是有用的. 缺省这个选项是禁止的. &lt;br /&gt;
'''{ping_interval, Seconds}'''&lt;br /&gt;
:多久发送一次 ping 给已连接的用户, 如果前一个选项被激活. 如果一个客户端连接在这个间隔内没有发送或接收任何节, 一个 ping 请求被发送给客户端. 缺省值为60秒. &lt;br /&gt;
'''{timeout_action, none|kill}'''&lt;br /&gt;
:当一个客户端在32秒内不回答一个服务器的ping请求时，服务器做什么. 缺省是什么也不做. &lt;br /&gt;
&lt;br /&gt;
这个例子激活了 Ping 应答, 配置该模块发送 pings 给4分钟内不活跃的客户端连接, 并且如果一个客户端在32秒内不回答 ping , 它的连接将被关闭:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_ping,  [{send_pings, true}, {ping_interval, 240}, {timeout_action, kill}]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_privacy====&lt;br /&gt;
&lt;br /&gt;
本模块实现定义于[[RFC3921|XMPP IM]]第十章的禁止通讯 (也被称为隐私规则) . 如果最终用户在他们的XMPP客户端也支持它, 他们将能够:&lt;br /&gt;
&lt;br /&gt;
* 收到某人的隐私列表privacy lists.&lt;br /&gt;
* 增加, 删除, 和修改某人的隐私列表privacy lists.&lt;br /&gt;
* 设置, 修改, 或减少激活的列表active lists.&lt;br /&gt;
* 设置, 修改, 或减少缺省列表default list (即, 缺省那个列表是激活的).&lt;br /&gt;
* 允许或禁止消息，基于JID, group, 或 订阅类型subscription type (或全局的).&lt;br /&gt;
* 允许或禁止入站的出席信息通知，基于JID, group, 或 订阅类型subscription type (或全局的).&lt;br /&gt;
* 允许或禁止出站的出席信息通知，基于JID, group, 或 订阅类型subscription type (或全局的).&lt;br /&gt;
* 允许或禁止IQ节，基于JID, group, 或 订阅类型subscription type (或全局的).&lt;br /&gt;
* 允许或禁止所有通讯，基于JID, group, 或 订阅类型subscription type (或全局的).&lt;br /&gt;
&lt;br /&gt;
:(从 http://xmpp.org/rfcs/rfc3921.html#privacy) &lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为禁止通讯(jabber:iq:privacy) IQ queries (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节)定义处理原则 .&lt;br /&gt;
&lt;br /&gt;
====mod_private====&lt;br /&gt;
&lt;br /&gt;
本模块增加对私有XML存储([[XEP-0049]])的支持:&lt;br /&gt;
&lt;br /&gt;
:使用这个方法, XMPP实体能存储私有数据到服务器并在任何必要的时候获得它. 存储的数据可以是任何东西, 只要它是合法的XML. 对这个namespace的一个典型的用法是服务器端存储特定客户端的配置; 另一个是标签存储([[XEP-0048]]). &lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为私有XML存储 (jabber:iq:private) IQ queries 定义处理原则(见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]]).&lt;br /&gt;
&lt;br /&gt;
====mod_proxy65====&lt;br /&gt;
&lt;br /&gt;
本模块实现SOCKS5字节流([[XEP-0065]]). 它允许把ejabberd当作一个在两个XMPP客户端之间的文件传输代理.&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{host, HostName}'''&lt;br /&gt;
:这个选项定义该服务的Jabber ID. 如果 host 选项没指定, Jabber ID将是该虚拟主机的hostname加上前缀‘proxy.’. 关键字 &amp;quot;@HOST@&amp;quot; 在启动时被替换为真实的虚拟主机名. &lt;br /&gt;
'''{name, Text}'''&lt;br /&gt;
:定义服务的服务发现名称. 缺省是 &amp;quot;SOCKS5 Bytestreams&amp;quot;. &lt;br /&gt;
'''{ip, IPTuple}'''&lt;br /&gt;
:这个选项定义监听哪个网络接口. 缺省是该服务的DNS名解析到的一个IP地址, 或, 如果失败, 则是{127,0,0,1}. &lt;br /&gt;
'''{port, Number}'''&lt;br /&gt;
:这个选项定义监听链入连接的端口. 缺省是 7777. &lt;br /&gt;
'''{hostname, HostName}'''&lt;br /&gt;
:定义一个在建立和客户端的会话时服务声明的hostname. 当你在一个NAT后面运行这个服务的时候这是有用的. 缺省是 ip 选项的值. 例如: &amp;quot;proxy.mydomain.org&amp;quot;, &amp;quot;200.150.100.50&amp;quot;. 注意在流协商的时候不是所有客户端都懂得域名, 所以在这个选项设定域名时你应该思考两次. &lt;br /&gt;
'''{auth_type, anonymous|plain}'''&lt;br /&gt;
:SOCKS5验证类型. 可能的值有 anonymous 和 plain. 缺省是 anonymous. &lt;br /&gt;
'''{access, AccessName}'''&lt;br /&gt;
:为文件传输发起者定义 ACL. 缺省是 all. &lt;br /&gt;
'''{max_connections, Number}'''&lt;br /&gt;
:每个文件传输的发起者的激活连接的最大数. 缺省不限制. &lt;br /&gt;
'''{shaper, none|ShaperName}'''&lt;br /&gt;
:这个选项为文件传输端定义塑性shaper. 有最大带宽的Shaper将被选择. 缺省是 none. &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 本模块最简单的配置:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_proxy65, []},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 更复杂的配置.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, proxy_users, {server, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {access, proxy65_access, [{allow, proxy_users}, {deny, all}]}.&lt;br /&gt;
&lt;br /&gt;
      {acl, admin, {user, &amp;quot;admin&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
      {shaper, proxyrate, {maxrate, 10240}}. %% 10 Kbytes/sec&lt;br /&gt;
      {access, proxy65_shaper, [{none, admin}, {proxyrate, proxy_users}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_proxy65, [{host, &amp;quot;proxy1.example.org&amp;quot;},&lt;br /&gt;
                       {name, &amp;quot;File Transfer Proxy&amp;quot;},&lt;br /&gt;
                       {ip, {200,150,100,1}},&lt;br /&gt;
                       {port, 7778},&lt;br /&gt;
                       {max_connections, 5},&lt;br /&gt;
                       {access, proxy65_access},&lt;br /&gt;
                       {shaper, proxy65_shaper}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_pubsub====&lt;br /&gt;
&lt;br /&gt;
本模块提供一个发行-订阅 服务 ([[XEP-0060]]). 在mod_pubsub里，功能可以使用插件来扩展. 实现PEP (基于Pubsub的个人信息事件) ([[XEP-0163]]) 的plugin, 在缺省的 ejabberd 配置文件中是被允许的, 并且它需要 mod_caps.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{host, HostName}'''&lt;br /&gt;
:这个选项定义了该服务的Jabber ID. 如果 host 选项没定义, Jabber ID将是该虚拟主机的hostname加上前缀‘pubsub.’. 关键字 &amp;quot;@HOST@&amp;quot; 在启动时被替换成真实的虚拟主机名. 如果你使用了 mod_pubsub_odbc, 请确保前缀只包含一个点dot, 例如‘pubsub.’, 或 ‘publish.’,. &lt;br /&gt;
'''{access_createnode, AccessName}'''&lt;br /&gt;
:这个选项使用 ACL 和 ACCESS来限制哪个用户被允许建立 pubsub 节点. 缺省本地ejabberd服务器的任何帐号被允许新建 pubsub 节点. &lt;br /&gt;
'''{max_items_node, MaxItems}'''&lt;br /&gt;
:定义可被一个节点存储的条目的最大数量. 缺省值为 10. &lt;br /&gt;
'''{plugins, [ Plugin, ...]}'''&lt;br /&gt;
:用于指定plugins使用哪个pubsub节点. 列表的第一个缺省被使用. 如果这个选项没定义, 缺省 plugins 列表为: [&amp;quot;flat&amp;quot;]. PubSub客户端能定义使用哪个plugin，当新建一个节点的时候: 增加 type=’plugin-name’ 属性到这个 create 节元素里. &lt;br /&gt;
'''{nodetree, Nodetree}'''&lt;br /&gt;
:用于指定使用哪个节点树 nodetree. 如果没定义, 缺省使用 pubsub nodetree : &amp;quot;tree&amp;quot;. 每个主机只能使用一个 nodetree , 且被所有节点 plugins 共享.&lt;br /&gt;
&lt;br /&gt;
:&amp;quot;virtual&amp;quot; nodetree 不把节点存储在数据库里. 它使用tons of nodes存储资源到系统. 如果使用 &amp;quot;virtual&amp;quot; nodetree, 你只能允许那些节点 plugins: [&amp;quot;flat&amp;quot;,&amp;quot;pep&amp;quot;] 或 [&amp;quot;flat&amp;quot;]; 任何其他 plugins 配置将不工作. 同时, 所有节点将有缺省配置, 并且不能被修改. 使用 &amp;quot;virtual&amp;quot; nodetree 需要从一个干净的数据库启动, 如果你之前使用了缺省的 &amp;quot;tree&amp;quot; nodetree，它将不工作.&lt;br /&gt;
&lt;br /&gt;
:&amp;quot;dag&amp;quot; nodetree 为 PubSub集合节点([[XEP-0248]])提供实验性的支持. 在那种情况下你也应该增加 &amp;quot;dag&amp;quot; 节点 plugin 作为缺省值, 例如: {plugins, [&amp;quot;dag&amp;quot;,&amp;quot;flat&amp;quot;,&amp;quot;hometree&amp;quot;,&amp;quot;pep&amp;quot;]} &lt;br /&gt;
'''{ignore_pep_from_offline, false|true}'''&lt;br /&gt;
:用于指定是否我们应该获取当我们连接时在我们的名册里处于离线状态的联系人的PEP最后发行条目. 值有 true 或 false. 如果不定义, pubsub 假定为 true，所以我们只能获取在线联系人的最后条目. &lt;br /&gt;
'''{last_item_cache, false|true}'''&lt;br /&gt;
:指定是否 pubsub 应该缓存最后条目. 值为 true 或 false. 如果没定义, pubsub不缓存最后条目. 在没有那么多节点的系统上, 缓存最后条目加速了 pubsub 并允许增加用户连接频率. 开销主要是内存使用, 因为每个条目都存储在内存里. &lt;br /&gt;
'''{pep_mapping, [ {Key, Value}, ...]}'''&lt;br /&gt;
:这允许定义一个 键-值 列表来在给定 PEP 名字空间选择定义节点 plugins . 以下例子将为每个拥有 tune namespace的PEP节点使用 node_tune 替代 node_pep :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {mod_pubsub, [{pep_mapping, [{&amp;quot;http://jabber.org/protocol/tune&amp;quot;, &amp;quot;tune&amp;quot;}]}]}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
配置例子使用 flat 节点作为缺省值, 并允许使用 flat, nodetree 和 pep 节点:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_pubsub, [&lt;br /&gt;
                {access_createnode, pubsub_createnode},&lt;br /&gt;
                {plugins, [&amp;quot;flat&amp;quot;, &amp;quot;hometree&amp;quot;, &amp;quot;pep&amp;quot;]}&lt;br /&gt;
               ]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
使用 ODBC 数据库要求使用重复的plugins. 以下例子展示前一个配置加上 ODBC 之后的用法:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_pubsub_odbc, [&lt;br /&gt;
                {access_createnode, pubsub_createnode},&lt;br /&gt;
                {plugins, [&amp;quot;flat_odbc&amp;quot;, &amp;quot;hometree_odbc&amp;quot;, &amp;quot;pep_odbc&amp;quot;]}&lt;br /&gt;
               ]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_register====&lt;br /&gt;
&lt;br /&gt;
本模块增加对带内注册([[XEP-0077]])的支持. 这个协议允许最终用户使用XMPP客户端做:&lt;br /&gt;
&lt;br /&gt;
* 在服务器注册一个新帐号.&lt;br /&gt;
* 在服务器上给一个现有帐号修改密码.&lt;br /&gt;
* 删除一个服务器上的现有帐号. &lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{access, AccessName}'''&lt;br /&gt;
:这个选项可被配置来指定限制注册的 rules. 如果一个 rule 在请求的用户名返回‘deny’, 那个用户名的注册被禁止. (缺省没有限制). &lt;br /&gt;
'''{access_from, AccessName}'''&lt;br /&gt;
:缺省的, ejabberd不允许从s2s或已有的c2s会话注册一个新帐号. 你可以修改它，通过在这个选项定义 access rule. 谨慎使用: 允许从s2s注册会导致流氓用户的不可控的大量帐号注册. &lt;br /&gt;
'''{welcome_message, Message}'''&lt;br /&gt;
:设定一个欢迎信息发送给每一个新注册的帐号. 第一个字符串是标题, 第二个字符串是消息 body. 在body里你可以用字符: \n 设定一个新行&lt;br /&gt;
'''{registration_watchers, [ JID, ...]}'''&lt;br /&gt;
:这个选项定义一个 JIDs 列表，每次有人注册新帐号，他们将收到通知. &lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为带内注册(jabber:iq:register) IQ queries (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节)定义处理原则. &lt;br /&gt;
&lt;br /&gt;
这个模块也从服务器读取另一个全局定义的选项: {registration_timeout, Timeout}. 这个选项限制从一个给定IP或用户名发出的注册请求的频率. 所以, 一个用户在前一个注册之后，经过这个数量的秒数之前不能从相同IP地址或JID注册一个新帐号. Timeout被表示为秒数, 并且必须是一个整数. 要禁止此限制, 把整数替换成单词，类似: infinity. 缺省值为: 600 秒.&lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 下个例子禁止注册太短的帐号名 prohibits:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, shortname, {user_glob, &amp;quot;?&amp;quot;}}.&lt;br /&gt;
      {acl, shortname, {user_glob, &amp;quot;??&amp;quot;}}.&lt;br /&gt;
      %% The same using regexp:&lt;br /&gt;
      %%{acl, shortname, {user_regexp, &amp;quot;^..?$&amp;quot;}}.&lt;br /&gt;
&lt;br /&gt;
      {access, register, [{deny, shortname},&lt;br /&gt;
                          {allow, all}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_register, [{access, register}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 这个配置禁止使用带内注册新建和删除帐号, 但允许现有帐号修改密码:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {access, register, [{deny, all}]}.&lt;br /&gt;
&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_register, [{access, register}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 这个配置禁止所有带内注册功能: 新建, 删除帐号和修改密码:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        %% {mod_register, [{access, register}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 定义一个欢迎信息和两个注册观察者. 也定义一个注册超时为一小时:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {registration_timeout, 3600}.&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_register,&lt;br /&gt;
         [&lt;br /&gt;
          {welcome_message, {&amp;quot;Welcome!&amp;quot;, &amp;quot;Hi.\nWelcome to this Jabber server.\n Check http://www.jabber.org\n\nBye&amp;quot;}},&lt;br /&gt;
          {registration_watchers, [&amp;quot;admin1@example.org&amp;quot;, &amp;quot;boss@example.net&amp;quot;]}&lt;br /&gt;
         ]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_roster====&lt;br /&gt;
&lt;br /&gt;
本模块实现名册管理，定义于 RFC 3921: [[RFC3921|XMPP IM]]. 也支持 名册版本 ([[XEP-0237]]).&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为名册管理 (jabber:iq:roster) IQ queries (see section [Ejabberd2:安装和操作指南[#iqdisc|3.3.2]] 节) 指定处理原则. &lt;br /&gt;
'''{versioning, false|true}'''&lt;br /&gt;
:激活名册版本. 这个选项缺省是禁止的. &lt;br /&gt;
'''{store_current_id, false|true}'''&lt;br /&gt;
:如果激活这个选项, 当前版本数量被存储在数据库. 如果被禁止, 版本数量在每次飞行计算. 激活这个选项同时减少ejabberd和数据库的负载. 任何情况下这个选项不影响客户端. 该选项只是当允许名册版本时有用. 该选项缺省是被禁止的. 重要: 如果你使用 mod_shared_roster, 你必须禁止这个选项. &lt;br /&gt;
&lt;br /&gt;
这个示例配置允许使用当前id存储的名册版本:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{modules,&lt;br /&gt;
 [&lt;br /&gt;
  ...&lt;br /&gt;
  {mod_roster, [{versioning, true}, {store_current_id, true}]},&lt;br /&gt;
  ...&lt;br /&gt;
 ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_service_log====&lt;br /&gt;
&lt;br /&gt;
本模块通过一个XMPP消息审计服务，例如Bandersnatch，增加了对最终用户的包进行记录的支持. 所有用户包被封装在一个 &amp;lt;route/&amp;gt; 元素里并发送给一个特定服务(们).&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{loggers, [Names, ...]}'''&lt;br /&gt;
:使用这个选项可以指定将接收包的一个 (列表之一) 服务(们). &lt;br /&gt;
&lt;br /&gt;
例子s:&lt;br /&gt;
&lt;br /&gt;
* 这是把所有的用户包记录到运行在bandersnatch.example.com的Bandersnatch 服务，:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_service_log, [{loggers, [&amp;quot;bandersnatch.example.com&amp;quot;]}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 这是把所有最终用户的包记录到运行在bandersnatch.example.com的Bandersnatch服务以及运行在bandersnatch.example.org的备份服务上:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_service_log, [{loggers, [&amp;quot;bandersnatch.example.com&amp;quot;,&lt;br /&gt;
                                      &amp;quot;bandersnatch.example.org&amp;quot;]}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_shared_roster====&lt;br /&gt;
&lt;br /&gt;
本模块允许你新建共享名册组. 这意味着你可以新建人员组，组里的成员从他们的名册里的其他组也可以看到成员. 这个功能的最大好处是最终用户不需要手工添加所有用户到他们的名册, 并且他们不能永久性地从共享名册组删除用户. 一个共享名册组可拥有来自任何XMPP服务器的成员, 但是出席信息from和to将只在创建该组的相同的虚拟主机的成员之间可用.&lt;br /&gt;
&lt;br /&gt;
共享名册组只可以通过Web管理编辑. 每个组有唯一标识符和以下参数:&lt;br /&gt;
&lt;br /&gt;
'''Name'''&lt;br /&gt;
:组名, 它将被显示在名册里. &lt;br /&gt;
'''Description'''&lt;br /&gt;
:组描述. 这个参数不影响任何东西. &lt;br /&gt;
'''Members'''&lt;br /&gt;
:组成员的完整JIDs列表, 在Web管理 里面每行一个. 为了把虚拟主机上的所有注册用户设为成员, 你可以使用特殊的参数: @all@. 注意这个参数被设计用于一个只有几百用户的小服务器. &lt;br /&gt;
'''Displayed groups'''&lt;br /&gt;
:那些成员将出现在名册上的组的列表. &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 假设一个计算机俱乐部希望它的所有成员在他们的名册里看到所有其他成员. 为了达到这点, 他们需要建立一个共享名册组类似下表: &lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|Identification ||Group ‘club_members’&lt;br /&gt;
|-&lt;br /&gt;
|Name ||俱乐部成员&lt;br /&gt;
|-&lt;br /&gt;
|Description ||来自计算机俱乐部的成员&lt;br /&gt;
|-&lt;br /&gt;
|Members ||&lt;br /&gt;
 {|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
 |member1@example.org &lt;br /&gt;
 |- &lt;br /&gt;
 |member2@example.org&lt;br /&gt;
 |-&lt;br /&gt;
 |member3@example.org &lt;br /&gt;
 |}&lt;br /&gt;
|-&lt;br /&gt;
|Displayed groups ||club_members&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* 在另一个情况下，我们有一个公司，它有三个部门: 管理部, 市场部和销售部. 所有组成员应该在他们的名册里看到其他成员. 另外, 所有经理应该在他们的名册里有所有市场部和销售部的人. 同时, 所有市场人员和全部销售队伍应该看到所有经理. 这个场景可由新建以下共享名册组来达到，如下表所示:&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|Identification ||	 Group ‘management’||Group ‘marketing’||	 Group ‘sales’&lt;br /&gt;
|-&lt;br /&gt;
|Name ||管理部 ||市场部 ||销售部&lt;br /&gt;
|-&lt;br /&gt;
|Description || || ||&lt;br /&gt;
|-&lt;br /&gt;
|Members ||&lt;br /&gt;
 {|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
 |manager1@example.org &lt;br /&gt;
 |- &lt;br /&gt;
 |manager2@example.org&lt;br /&gt;
 |-&lt;br /&gt;
 |manager3@example.org &lt;br /&gt;
 |-&lt;br /&gt;
 |manager4@example.org &lt;br /&gt;
 |}&lt;br /&gt;
||&lt;br /&gt;
 {|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
 |marketeer1@example.org &lt;br /&gt;
 |- &lt;br /&gt;
 |marketeer2@example.org&lt;br /&gt;
 |-&lt;br /&gt;
 |marketeer3@example.org &lt;br /&gt;
 |-&lt;br /&gt;
 |marketeer4@example.org &lt;br /&gt;
 |}&lt;br /&gt;
||&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
 |saleswoman1@example.org &lt;br /&gt;
 |- &lt;br /&gt;
 |salesman1@example.org&lt;br /&gt;
 |-&lt;br /&gt;
 |saleswoman2@example.org &lt;br /&gt;
 |-&lt;br /&gt;
 |alesman2@example.org &lt;br /&gt;
 |}&lt;br /&gt;
|-&lt;br /&gt;
|Displayed groups ||&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
 |管理 &lt;br /&gt;
 |- &lt;br /&gt;
 |市场&lt;br /&gt;
 |-&lt;br /&gt;
 |销售 &lt;br /&gt;
 |}&lt;br /&gt;
||&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
 |管理 &lt;br /&gt;
 |- &lt;br /&gt;
 |市场&lt;br /&gt;
 |}&lt;br /&gt;
||&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
 |管理 &lt;br /&gt;
 |-&lt;br /&gt;
 |销售 &lt;br /&gt;
 |}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====mod_sic====&lt;br /&gt;
&lt;br /&gt;
本模块增加了对服务器IP检查 ([[XEP-0279]])的支持. 这个协议允许客户端发现它的外部IP地址.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为urn:xmpp:sic:0 IQ queries (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节)定义了处理原则 .&lt;br /&gt;
&lt;br /&gt;
====mod_stats====&lt;br /&gt;
&lt;br /&gt;
This module adds support for Statistics Gathering (XEP-0039). This protocol allows you to retrieve next statistics from your ejabberd deployment:&lt;br /&gt;
&lt;br /&gt;
* Total number of registered users on the current virtual host (users/total).&lt;br /&gt;
* Total number of registered users on all virtual hosts (users/all-hosts/total).&lt;br /&gt;
* Total number of online users on the current virtual host (users/online).&lt;br /&gt;
* Total number of online users on all virtual hosts (users/all-hosts/online). &lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为统计信息收集 (http://jabber.org/protocol/stats) IQ queries (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节) 定义了处理原则. &lt;br /&gt;
&lt;br /&gt;
因为只有少量的客户端 (例如 Tkabber) 和软件库支持这个 XEP, 一些例子以 XML 方式给出 ，为了获得统计信息，你需要发送它. 它们是:&lt;br /&gt;
&lt;br /&gt;
* 你可以请求当前虚拟主机 (example.org)的在线用户数量:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;iq to='example.org' type='get'&amp;gt;&lt;br /&gt;
        &amp;lt;query xmlns='http://jabber.org/protocol/stats'&amp;gt;&lt;br /&gt;
          &amp;lt;stat name='users/online'/&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
      &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 你可以请求所有虚拟主机上注册用户的总数量:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;iq to='example.org' type='get'&amp;gt;&lt;br /&gt;
        &amp;lt;query xmlns='http://jabber.org/protocol/stats'&amp;gt;&lt;br /&gt;
          &amp;lt;stat name='users/all-hosts/total'/&amp;gt;&lt;br /&gt;
        &amp;lt;/query&amp;gt;&lt;br /&gt;
      &amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_time====&lt;br /&gt;
&lt;br /&gt;
本模块功能支持实体时间 ([[XEP-0202]]). 通过使用这个 XEP, 你能发现另一个实体所在位置的时间.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为实体时间 (jabber:iq:time) IQ queries (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节)定义了处理原则 .&lt;br /&gt;
&lt;br /&gt;
====mod_vcard====&lt;br /&gt;
&lt;br /&gt;
本模块允许最终用户存储和接收他们的电子名片vCard, 以及接收别的用户的电子名片vCards, 定义于 vcard-temp ([[XEP-0054]]). 这个模块也实现了一个基于这些用户的vCards的简单的Jabber用户目录. 进一步的, 当收到请求时它允许服务器发送它自己的名片vCard.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{host, HostName}'''&lt;br /&gt;
:这个选项定义该服务的Jabber ID. 如果 host 选项没定义, Jabber ID将是该虚拟主机的hostname加前缀‘vjud.’. 关键字 &amp;quot;@HOST@&amp;quot; 在启动时被替换成真实的虚拟主机名. &lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为vcard-temp IQ queries (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节)定义了处理原则 . &lt;br /&gt;
'''{search, true|false}'''&lt;br /&gt;
:这个选项定义是否允许搜索功能，如果禁止，选项 host 将被忽略，并且 Jabber用户目录服务将不出现在服务发现条目列表里. 缺省值为true. &lt;br /&gt;
'''{matches, infinity|Number}'''&lt;br /&gt;
:使用这个选项, 搜索结果的数量将被限制. 如果这下选项的值设为 infinity, 所有搜索结果被汇报. 缺省值为 30. &lt;br /&gt;
'''{allow_return_all, false|true}'''&lt;br /&gt;
:这个选项允许你指定是否输入字段为空来进行搜索操作应该返回所有已在他们的vCard中加入信息的用户. 缺省值为 false. &lt;br /&gt;
'''{search_all_hosts, true|false}'''&lt;br /&gt;
:如果这个选项设为 true, 搜索操作将应用于所有虚拟主机. 反之只有当前主机将被搜索. 缺省值为 true. 这个选项在 mod_vcard 是可用的, 但是在 mod_vcard_odbc 是不可用的. &lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 在第一种情况下, 搜索结果被限制为20个条目, 当人们做空的搜索时，每个添加了信息到他们的vCard的用户将被列出 , 并且只有当前主机的用户会被返回:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_vcard, [{search, true},&lt;br /&gt;
                     {matches, 20},&lt;br /&gt;
                     {allow_return_all, true},&lt;br /&gt;
                     {search_all_hosts, false}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 第二种情况不同在于，搜索结果是不限制的, 并且所有虚拟主机将被搜索而不是只有当前主机:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_vcard, [{search, true},&lt;br /&gt;
                     {matches, infinity},&lt;br /&gt;
                     {allow_return_all, true}]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_vcard_ldap====&lt;br /&gt;
&lt;br /&gt;
ejabberd能映射LDAP属性到vCard字段. 这个行为在 mod_vcard_ldap 模块实现. 本模块不依赖于验证方法 (见 [[Ejabberd2:安装和操作指南#LDAP|3.2.5]] 节).&lt;br /&gt;
&lt;br /&gt;
经常的 ejabberd 对待 LDAP 像一个只读存储器: 它可能查看数据, 但是不能新建帐号或编辑存储在LDAP里的 vCard. 无论如何, 修改密码是可能的，如果 mod_register 模块激活了并且 LDAP 服务器支持 [http://tools.ietf.org/html/rfc3062 RFC 3062].&lt;br /&gt;
&lt;br /&gt;
mod_vcard_ldap模块有它自己的可选参数. 第一组参数和设定验证方法时的顶极LDAP参数含义相同: ldap_servers, ldap_port, ldap_rootdn, ldap_password, ldap_base, ldap_uids, and ldap_filter. 见 [[Ejabberd2:安装和操作指南#LDAP|3.2.5]] 节查看关于这些选项的详细信息. 如果这些选项中的一个没有设置, ejabberd将以相同哦功能名字查找顶极选项.&lt;br /&gt;
&lt;br /&gt;
第二组参数包括以下的 mod_vcard_ldap-专有 选项:&lt;br /&gt;
&lt;br /&gt;
'''{host, HostName}'''&lt;br /&gt;
:这个选项定义该服务的Jabber ID. 如果 host 选项没定义, Jabber ID将是该虚拟主机的hostname加上前缀‘vjud.’. 关键字 &amp;quot;@HOST@&amp;quot; 在启动时被替换成真实的虚拟主机名. &lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为 vcard-temp IQ queries (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节)定义了处理原则 . &lt;br /&gt;
'''{search, true|false}'''&lt;br /&gt;
:这个选项指定是否搜索功能被允许(值: true) 或禁止(值: false). 如果禁止, 选项 host 将被忽略，并且Jabber用户目录服务将不出现在服务发现条目列表里. 缺省值为 true. &lt;br /&gt;
'''{matches, infinity|Number}'''&lt;br /&gt;
:使用这个选项, 搜索结果的数量被限制. 如果该选项值设为 infinity, 所有结果被汇报. 缺省值为 30. &lt;br /&gt;
'''{ldap_vcard_map, [ {Name, Pattern, LDAPattributes}, ...]}'''&lt;br /&gt;
:使用此选项，你可以设置一个表，映射LDAP属性到vCard字段. Name是 vCard 的类型名，定义于 [http://tools.ietf.org/html/rfc2426 RFC 2426]. Pattern是一个字符串，包含 pattern 变量 &amp;quot;%u&amp;quot;, &amp;quot;%d&amp;quot; 或 &amp;quot;%s&amp;quot;. LDAPattributes 是包含LDAP属性的列表. pattern变量 &amp;quot;%s&amp;quot; 将被从 List_of_LDAP_attributes顺序替换成 LDAP 属性值, &amp;quot;%u&amp;quot; 将被替换成一个JID的user部分, 而&amp;quot;%d&amp;quot; 将被替换成一个JID的domain部分. 缺省为:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    [{&amp;quot;NICKNAME&amp;quot;, &amp;quot;%u&amp;quot;, []},&lt;br /&gt;
     {&amp;quot;FN&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;displayName&amp;quot;]},&lt;br /&gt;
     {&amp;quot;LAST&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;sn&amp;quot;]},&lt;br /&gt;
     {&amp;quot;FIRST&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;givenName&amp;quot;]},&lt;br /&gt;
     {&amp;quot;MIDDLE&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;initials&amp;quot;]},&lt;br /&gt;
     {&amp;quot;ORGNAME&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;o&amp;quot;]},&lt;br /&gt;
     {&amp;quot;ORGUNIT&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;ou&amp;quot;]},&lt;br /&gt;
     {&amp;quot;CTRY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;c&amp;quot;]},&lt;br /&gt;
     {&amp;quot;LOCALITY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;l&amp;quot;]},&lt;br /&gt;
     {&amp;quot;STREET&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;street&amp;quot;]},&lt;br /&gt;
     {&amp;quot;REGION&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;st&amp;quot;]},&lt;br /&gt;
     {&amp;quot;PCODE&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;postalCode&amp;quot;]},&lt;br /&gt;
     {&amp;quot;TITLE&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;title&amp;quot;]},&lt;br /&gt;
     {&amp;quot;URL&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;labeleduri&amp;quot;]},&lt;br /&gt;
     {&amp;quot;DESC&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;description&amp;quot;]},&lt;br /&gt;
     {&amp;quot;TEL&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;telephoneNumber&amp;quot;]},&lt;br /&gt;
     {&amp;quot;EMAIL&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;mail&amp;quot;]},&lt;br /&gt;
     {&amp;quot;BDAY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;birthDay&amp;quot;]},&lt;br /&gt;
     {&amp;quot;ROLE&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;employeeType&amp;quot;]},&lt;br /&gt;
     {&amp;quot;PHOTO&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;jpegPhoto&amp;quot;]}]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''{ldap_search_fields, [ {Name, Attribute}, ...]}'''&lt;br /&gt;
:这个选项定义搜索表单和参与搜索的LDAP属性. Name 是搜索表单字段的名字，它将使用翻译文件自动翻译 (查看 msgs/*.msg 找寻可用的单词). Attribute 是LDAP属性或 pattern &amp;quot;%u&amp;quot;. 缺省值是:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    [{&amp;quot;User&amp;quot;, &amp;quot;%u&amp;quot;},&lt;br /&gt;
     {&amp;quot;Full Name&amp;quot;, &amp;quot;displayName&amp;quot;},&lt;br /&gt;
     {&amp;quot;Given Name&amp;quot;, &amp;quot;givenName&amp;quot;},&lt;br /&gt;
     {&amp;quot;Middle Name&amp;quot;, &amp;quot;initials&amp;quot;},&lt;br /&gt;
     {&amp;quot;Family Name&amp;quot;, &amp;quot;sn&amp;quot;},&lt;br /&gt;
     {&amp;quot;Nickname&amp;quot;, &amp;quot;%u&amp;quot;},&lt;br /&gt;
     {&amp;quot;Birthday&amp;quot;, &amp;quot;birthDay&amp;quot;},&lt;br /&gt;
     {&amp;quot;Country&amp;quot;, &amp;quot;c&amp;quot;},&lt;br /&gt;
     {&amp;quot;City&amp;quot;, &amp;quot;l&amp;quot;},&lt;br /&gt;
     {&amp;quot;Email&amp;quot;, &amp;quot;mail&amp;quot;},&lt;br /&gt;
     {&amp;quot;Organization Name&amp;quot;, &amp;quot;o&amp;quot;},&lt;br /&gt;
     {&amp;quot;Organization Unit&amp;quot;, &amp;quot;ou&amp;quot;}]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''{ldap_search_reported, [ {SearchField, VcardField}, ...]}'''&lt;br /&gt;
:这个选项定义哪个搜索字段应该汇报. SearchField 是一个搜索表单的字段名，它将使用翻译文件自动翻译 (去 msgs/*.msg 查看可用的单词). VcardField 是vCard 字段名，定义于 ldap_vcard_map 选项. 缺省为:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
    [{&amp;quot;Full Name&amp;quot;, &amp;quot;FN&amp;quot;},&lt;br /&gt;
     {&amp;quot;Given Name&amp;quot;, &amp;quot;FIRST&amp;quot;},&lt;br /&gt;
     {&amp;quot;Middle Name&amp;quot;, &amp;quot;MIDDLE&amp;quot;},&lt;br /&gt;
     {&amp;quot;Family Name&amp;quot;, &amp;quot;LAST&amp;quot;},&lt;br /&gt;
     {&amp;quot;Nickname&amp;quot;, &amp;quot;NICKNAME&amp;quot;},&lt;br /&gt;
     {&amp;quot;Birthday&amp;quot;, &amp;quot;BDAY&amp;quot;},&lt;br /&gt;
     {&amp;quot;Country&amp;quot;, &amp;quot;CTRY&amp;quot;},&lt;br /&gt;
     {&amp;quot;City&amp;quot;, &amp;quot;LOCALITY&amp;quot;},&lt;br /&gt;
     {&amp;quot;Email&amp;quot;, &amp;quot;EMAIL&amp;quot;},&lt;br /&gt;
     {&amp;quot;Organization Name&amp;quot;, &amp;quot;ORGNAME&amp;quot;},&lt;br /&gt;
     {&amp;quot;Organization Unit&amp;quot;, &amp;quot;ORGUNIT&amp;quot;}]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例子:&lt;br /&gt;
&lt;br /&gt;
* 假设 ldap.example.org 是我们的一个LDAP服务器的名字. 我们有用户，他们的密码在 &amp;quot;ou=Users,dc=example,dc=org&amp;quot; 目录. 同时我们也有地址簿 addressbook, 它包含用户的 emails 和他们的其他信息， 在 &amp;quot;ou=AddressBook,dc=example,dc=org&amp;quot; 目录. 相应的验证节应该看起来是这样:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      %% 验证方法&lt;br /&gt;
      {auth_method, ldap}.&lt;br /&gt;
      %% 我们的LDAP服务器的DNS名&lt;br /&gt;
      {ldap_servers, [&amp;quot;ldap.example.org&amp;quot;]}.&lt;br /&gt;
      %% 我们想授权的用户仅为 'shadowAccount' object class&lt;br /&gt;
      {ldap_filter, &amp;quot;(objectClass=shadowAccount)&amp;quot;}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;现在我们想使用用户的 LDAP-信息 作为他们的 vCards. 我们在我们的 LDAP schema定义了四个属性: &amp;quot;mail&amp;quot; — emai地址, &amp;quot;givenName&amp;quot; — 名, &amp;quot;sn&amp;quot; — 姓, &amp;quot;birthDay&amp;quot; — 生日. 我们也想用户搜索到每个其他人. 让我们看一下如何设置:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {modules,&lt;br /&gt;
        ...&lt;br /&gt;
        {mod_vcard_ldap,&lt;br /&gt;
         [&lt;br /&gt;
          %% We use the same server and port, but want to bind anonymously because&lt;br /&gt;
          %% our LDAP server accepts anonymous requests to&lt;br /&gt;
          %% &amp;quot;ou=AddressBook,dc=example,dc=org&amp;quot; subtree.&lt;br /&gt;
          {ldap_rootdn, &amp;quot;&amp;quot;},&lt;br /&gt;
          {ldap_password, &amp;quot;&amp;quot;},&lt;br /&gt;
          %% define the addressbook's base&lt;br /&gt;
          {ldap_base, &amp;quot;ou=AddressBook,dc=example,dc=org&amp;quot;},&lt;br /&gt;
          %% uidattr: user's part of JID is located in the &amp;quot;mail&amp;quot; attribute&lt;br /&gt;
          %% uidattr_format: common format for our emails&lt;br /&gt;
          {ldap_uids, [{&amp;quot;mail&amp;quot;,&amp;quot;%u@mail.example.org&amp;quot;}]},&lt;br /&gt;
          %% We have to define empty filter here, because entries in addressbook does not&lt;br /&gt;
          %% belong to shadowAccount object class&lt;br /&gt;
          {ldap_filter, &amp;quot;&amp;quot;},&lt;br /&gt;
          %% Now we want to define vCard pattern&lt;br /&gt;
          {ldap_vcard_map,&lt;br /&gt;
           [{&amp;quot;NICKNAME&amp;quot;, &amp;quot;%u&amp;quot;, []}, % just use user's part of JID as his nickname&lt;br /&gt;
            {&amp;quot;FIRST&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;givenName&amp;quot;]},&lt;br /&gt;
            {&amp;quot;LAST&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;sn&amp;quot;]},&lt;br /&gt;
            {&amp;quot;FN&amp;quot;, &amp;quot;%s, %s&amp;quot;, [&amp;quot;sn&amp;quot;, &amp;quot;givenName&amp;quot;]}, % example: &amp;quot;Smith, John&amp;quot;&lt;br /&gt;
            {&amp;quot;EMAIL&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;mail&amp;quot;]},&lt;br /&gt;
            {&amp;quot;BDAY&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;birthDay&amp;quot;]}]},&lt;br /&gt;
          %% Search form&lt;br /&gt;
          {ldap_search_fields,&lt;br /&gt;
           [{&amp;quot;User&amp;quot;, &amp;quot;%u&amp;quot;},&lt;br /&gt;
            {&amp;quot;Name&amp;quot;, &amp;quot;givenName&amp;quot;},&lt;br /&gt;
            {&amp;quot;Family Name&amp;quot;, &amp;quot;sn&amp;quot;},&lt;br /&gt;
            {&amp;quot;Email&amp;quot;, &amp;quot;mail&amp;quot;},&lt;br /&gt;
            {&amp;quot;Birthday&amp;quot;, &amp;quot;birthDay&amp;quot;}]},&lt;br /&gt;
          %% vCard fields to be reported&lt;br /&gt;
          %% Note that JID is always returned with search results&lt;br /&gt;
          {ldap_search_reported,&lt;br /&gt;
           [{&amp;quot;Full Name&amp;quot;, &amp;quot;FN&amp;quot;},&lt;br /&gt;
            {&amp;quot;Nickname&amp;quot;, &amp;quot;NICKNAME&amp;quot;},&lt;br /&gt;
            {&amp;quot;Birthday&amp;quot;, &amp;quot;BDAY&amp;quot;}]}&lt;br /&gt;
        ]}&lt;br /&gt;
        ...&lt;br /&gt;
      }.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:注意 mod_vcard_ldap 模块在LDAP搜索用户的信息之前会先检查用户是否存在.&lt;br /&gt;
&lt;br /&gt;
* ldap_vcard_map 例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {ldap_vcard_map,&lt;br /&gt;
       [{&amp;quot;NICKNAME&amp;quot;, &amp;quot;%u&amp;quot;, []},&lt;br /&gt;
        {&amp;quot;FN&amp;quot;, &amp;quot;%s&amp;quot;, [&amp;quot;displayName&amp;quot;]},&lt;br /&gt;
        {&amp;quot;CTRY&amp;quot;, &amp;quot;Russia&amp;quot;, []},&lt;br /&gt;
        {&amp;quot;EMAIL&amp;quot;, &amp;quot;%u@%d&amp;quot;, []},&lt;br /&gt;
        {&amp;quot;DESC&amp;quot;, &amp;quot;%s\n%s&amp;quot;, [&amp;quot;title&amp;quot;, &amp;quot;description&amp;quot;]}&lt;br /&gt;
       ]},&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* ldap_search_fields 例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {ldap_search_fields,&lt;br /&gt;
       [{&amp;quot;User&amp;quot;, &amp;quot;uid&amp;quot;},&lt;br /&gt;
        {&amp;quot;Full Name&amp;quot;, &amp;quot;displayName&amp;quot;},&lt;br /&gt;
        {&amp;quot;Email&amp;quot;, &amp;quot;mail&amp;quot;}&lt;br /&gt;
       ]},&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* ldap_search_reported 例子:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {ldap_search_reported,&lt;br /&gt;
       [{&amp;quot;Full Name&amp;quot;, &amp;quot;FN&amp;quot;},&lt;br /&gt;
        {&amp;quot;Email&amp;quot;, &amp;quot;EMAIL&amp;quot;},&lt;br /&gt;
        {&amp;quot;Birthday&amp;quot;, &amp;quot;BDAY&amp;quot;},&lt;br /&gt;
        {&amp;quot;Nickname&amp;quot;, &amp;quot;NICKNAME&amp;quot;}&lt;br /&gt;
       ]},&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mod_vcard_xupdate====&lt;br /&gt;
&lt;br /&gt;
用户的客户端能在该用户的vCard存储一个头像. 基于vCard的头像 协议 ([[XEP-0153]]) 提供了一个方法给客户端来通知联系人他的头像的哈希值. 然而, 简单或小的客户端可能没有实现那个协议.&lt;br /&gt;
&lt;br /&gt;
如果本模块被激活, 所有出站的客户端出席信息节代替客户端自动获得头像哈希值. 所以, 联系人收到这个带有更新数据的出席信息节(见 [[XEP-0153]])，就好像客户端自己把它插入进去的一样. 如果客户端已经在出席信息节里包含了这样的元素, 它被替换成 ejabberd 生成的元素.&lt;br /&gt;
&lt;br /&gt;
通过激活本模块, 每次 vCard 修改就重新进行一次哈希值计算, 每个由客户端发送的出席信息导致一次哈希值接收，以及一次出席信息节的重写. 因此, 激活本模块将在服务器发生一些计算开销，如果客户端频繁修改他们的出席信息的话.&lt;br /&gt;
&lt;br /&gt;
====mod_version====&lt;br /&gt;
&lt;br /&gt;
本模块实现软件版本([[XEP-0092]]). 所以, 当被查询时它应答 ejabberd 的版本.&lt;br /&gt;
&lt;br /&gt;
选项:&lt;br /&gt;
&lt;br /&gt;
'''{show_os, true|false}'''&lt;br /&gt;
:是否应该显示操作系统. 缺省值是 true. &lt;br /&gt;
'''{iqdisc, Discipline}'''&lt;br /&gt;
:这为软件版本(jabber:iq:version) IQ queries (见 [[Ejabberd2:安装和操作指南#iqdisc|3.3.2]] 节)定义了处理原则 .&lt;br /&gt;
&lt;br /&gt;
==管理ejabberd服务器==&lt;br /&gt;
===ejabberdctl===&lt;br /&gt;
&lt;br /&gt;
使用ejabberdctl命令行管理脚本，你可以执行ejabberdctl命令(详见下一节, [[Ejabberd2:安装和操作指南#ejabberdctl命令|4.1.1]]) 和一些普通的 ejabberd 命令 (详见 [[[[Ejabberd2:安装和操作指南#ejabberd命令|4.2]]). 这意味着你可以在一个本地或远程ejabberd服务器(通过提供参数 --node NODENAME)上启动，停止以及执行一些其他的管理任务.&lt;br /&gt;
&lt;br /&gt;
ejabberdctl脚本可在文件 ejabberdctl.cfg 里配置. 这个文件包含每个可配置的选项的详细的信息. 见 [[Ejabberd2:安装和操作指南#Erlang运行时系统|4.1.2]] 节.&lt;br /&gt;
&lt;br /&gt;
ejabberdctl脚本返回数字状态码. 成功显示为 0, 错误显示为 1, 其它码可被用于特定结果. 这可以由其他脚本使用，来自动决定一个命令是否成功, 例如使用: echo $?&lt;br /&gt;
&lt;br /&gt;
====ejabberdctl命令====&lt;br /&gt;
&lt;br /&gt;
不带任何参数执行 ejabberdctl时, 它显示可用的选项. 如果没有一个 ejabberd 服务器在运行, 可用的参数是:&lt;br /&gt;
&lt;br /&gt;
'''start'''&lt;br /&gt;
:以后台模式启动ejabberd. 这是缺省方法. &lt;br /&gt;
'''debug'''&lt;br /&gt;
:连接一个 Erlang shell 到一个已存在的 ejabberd 服务器. 这允许在ejabberd服务器上执行交互命令. &lt;br /&gt;
'''live'''&lt;br /&gt;
:以live模式启动 ejabberd: shell 保持连接到已启动的服务器, 显示日志信息并允许执行交互命令. &lt;br /&gt;
&lt;br /&gt;
如果已经有一个ejabberd服务器在系统里运行, ejabberdctl 展示以下 ejabberdctl 命令以及那台服务器上所有可用的 ejabberd 命令 (见 [[Ejabberd2:安装和操作指南#ejabberd命令|4.2.1]] 节).&lt;br /&gt;
&lt;br /&gt;
ejabberdctl命令如下:&lt;br /&gt;
&lt;br /&gt;
'''help'''&lt;br /&gt;
:获得关于ejabberdctl或任何可用的命令的帮助. 试下 ejabberdctl help help. &lt;br /&gt;
'''status'''&lt;br /&gt;
:检查ejabberd服务器的状态. &lt;br /&gt;
'''stop'''&lt;br /&gt;
:停止ejabberd服务器. &lt;br /&gt;
'''restart'''&lt;br /&gt;
:重启ejabberd服务器. &lt;br /&gt;
'''mnesia'''&lt;br /&gt;
:获得关于Mnesia数据库的信息. &lt;br /&gt;
&lt;br /&gt;
ejabberdctl脚本可被限制为需要验证并执行一些 ejabberd命令; 见 [[Ejabberd2:安装和操作指南#用AccessCommands限制执行|4.2.2]] 节. 增加这个选项到文件 ejabberd.cfg. 在这个例子没有限制:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{ejabberdctl_access_commands, []}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果账号 robot1@example.org 被注册到 ejabberd ，以密码 abcdef (使用 MD5 为 E8B501798950FC58AAD83C8C14978E), 并且 ejabberd.cfg 包含以下设定:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{hosts, [&amp;quot;example.org&amp;quot;]}.&lt;br /&gt;
{acl, bots, {user, &amp;quot;robot1&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
{access, ctlaccess, [{allow, bots}]}.&lt;br /&gt;
{ejabberdctl_access_commands, [ {ctlaccess, [registered_users, register], []} ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
那么你可以在 shell 里做这个:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ejabberdctl registered_users example.org&lt;br /&gt;
Error: no_auth_provided&lt;br /&gt;
$ ejabberdctl --auth robot1 example.org E8B501798950FC58AAD83C8C14978E registered_users example.org&lt;br /&gt;
robot1&lt;br /&gt;
testuser1&lt;br /&gt;
testuser2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Erlang运行时系统====&lt;br /&gt;
&lt;br /&gt;
ejabberd是一个 Erlang/OTP 应用，运行在一个Erlang运行时系统内部. 这个系统是用环境变量和命令行参数来配置的. ejabberdctl管理脚本可能会使用其中的一些. 你可以在ejabberdctl.cfg文件里配置其中的一部分, 里面已包含了关于它们的详细描述. 本节描述所有环境变量和命令行参数的参考.&lt;br /&gt;
&lt;br /&gt;
环境变量:&lt;br /&gt;
&lt;br /&gt;
'''EJABBERD_CONFIG_PATH'''&lt;br /&gt;
:ejabberd配置文件的路径. &lt;br /&gt;
'''EJABBERD_MSGS_PATH'''&lt;br /&gt;
:翻译字符串的目录路径. &lt;br /&gt;
'''EJABBERD_LOG_PATH'''&lt;br /&gt;
:ejabberd服务日志文件的路径. &lt;br /&gt;
'''EJABBERD_SO_PATH'''&lt;br /&gt;
:二进制系统库的目录路径. &lt;br /&gt;
'''EJABBERD_DOC_PATH'''&lt;br /&gt;
:ejabberd文档的目录路径. &lt;br /&gt;
'''EJABBERD_PID_PATH'''&lt;br /&gt;
:ejabberd启动时建立的PID文件的路径. &lt;br /&gt;
'''HOME'''&lt;br /&gt;
:ejabberd的家Home目录的路径. 这个路径用于读取文件 .erlang.cookie. &lt;br /&gt;
'''ERL_CRASH_DUMP'''&lt;br /&gt;
:崩溃报告dump文件的路径. &lt;br /&gt;
'''ERL_INETRC'''&lt;br /&gt;
:指示使用名字解析的哪个IP. 如果使用 -sname, 要么指定这个选项，要么指定 -kernel inetrc filepath. &lt;br /&gt;
'''ERL_MAX_PORTS'''&lt;br /&gt;
:并发开放的Erlang端口的最大数量. &lt;br /&gt;
'''ERL_MAX_ETS_TABLES'''&lt;br /&gt;
:ETS和Mnesia表的最大数量. &lt;br /&gt;
&lt;br /&gt;
命令行参数:&lt;br /&gt;
&lt;br /&gt;
'''-sname ejabberd'''&lt;br /&gt;
:这个Erlang节点将只使用主机名的第一部分来指定, 即，本域之外的其他Erlang节点不能够联系联络这个节点. 在大多数情况下这是可取的. &lt;br /&gt;
'''-name ejabberd'''&lt;br /&gt;
:这个Erlang节点将被完全指定. 这只在如果你计划在不同的网络配置一个ejabberd集群时有用. &lt;br /&gt;
'''-kernel inetrc ’&amp;quot;/etc/ejabberd/inetrc&amp;quot;’'''&lt;br /&gt;
:指出使用名字解析的哪个IP. 如果使用 -sname, 要么指定这个选项，要么指定 ERL_INETRC. &lt;br /&gt;
'''-kernel inet_dist_listen_min 4200 inet_dist_listen_min 4210'''&lt;br /&gt;
:定义 epmd ( [[Ejabberd2:安装和操作指南#epmd|5.2]] 节)可以监听的第一个和最后一个端口. &lt;br /&gt;
'''-detached'''&lt;br /&gt;
:启动Erlang系统并从系统控制台分离. 运行守护进程和后台进程时有用. &lt;br /&gt;
'''-noinput'''&lt;br /&gt;
:确保Erlang系统不尝试读任何输入. 运行守护进程和后台进程时有用. &lt;br /&gt;
'''-pa /var/lib/ejabberd/ebin'''&lt;br /&gt;
:指定Erlang二进制文件(*.beam)所在目录. &lt;br /&gt;
'''-s ejabberd'''&lt;br /&gt;
:告诉Erlang运行时系统启动ejabberd应用. &lt;br /&gt;
'''-mnesia dir ’&amp;quot;/var/lib/ejabberd/&amp;quot;’'''&lt;br /&gt;
:指定Mnesia数据库目录. &lt;br /&gt;
'''-sasl sasl_error_logger {file, &amp;quot;/var/log/ejabberd/erlang.log&amp;quot;}'''&lt;br /&gt;
:Erlang/OTP系统日志文件的路径. 这里SASL意味着 系统架构支持库“System Architecture Support Libraries” 而不是 简单验证和安全层 “Simple Authentication and Security Layer”. &lt;br /&gt;
'''+K [true|false]'''&lt;br /&gt;
:内核轮询. &lt;br /&gt;
'''-smp [auto|enable|disable]'''&lt;br /&gt;
:SMP(多CPU)支持. &lt;br /&gt;
'''+P 250000'''&lt;br /&gt;
:Erlang进程的最大数量. &lt;br /&gt;
'''-remsh ejabberd@localhost'''&lt;br /&gt;
:在一个远程Erlang节点打开一个Erlang shell. &lt;br /&gt;
'''-hidden'''&lt;br /&gt;
:到其他节点的连接是隐藏的(没有公开发布). 结果是这个节点不被认为是集群的一部分. 当启动一个临时的ctl或debug节点的时候这是很重要的. &lt;br /&gt;
&lt;br /&gt;
注意当使用shell脚本的时候一些字符需要逃逸, 例如 &amp;quot; 和 {}. 你可在Erlang手册页 (erl -man erl)找到其他选项.&lt;br /&gt;
&lt;br /&gt;
===ejabberd命令===&lt;br /&gt;
&lt;br /&gt;
一个ejabberd命令是一个通过名字指定的抽象函数, 在ejabberd_commands 服务里注册并有一个已定义的编号和出入和输出类型. 那些命令能被定义在任何Erlang模块并使用任何合法的前端执行.&lt;br /&gt;
&lt;br /&gt;
ejabberd包含一个前端用来执行ejabberd命令: 脚本ejabberdctl. 其他可被安装以不同方式来执行ejabberd命令的已知的前端有: ejabberd_xmlrpc (XML-RPC 服务), mod_rest (HTTP POST 服务), mod_shcommands (ejabberd WebAdmin 页面).&lt;br /&gt;
&lt;br /&gt;
====ejabberd命令清单====&lt;br /&gt;
&lt;br /&gt;
ejabberd缺省包含了一些ejabberd命令. 当更多模块被安装, 在前端又会有新命令可以用.&lt;br /&gt;
&lt;br /&gt;
获得可用命令和它们的帮助的最容易的方法, 是使用ejabberdctl脚本:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ejabberdctl help&lt;br /&gt;
Usage: ejabberdctl [--node nodename] [--auth user host password] command [options]&lt;br /&gt;
&lt;br /&gt;
Available commands in this ejabberd node:&lt;br /&gt;
  backup file                  Store the database to backup file&lt;br /&gt;
  connected_users              List all established sessions&lt;br /&gt;
  connected_users_number       Get the number of established sessions&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
最多人感兴趣的是:&lt;br /&gt;
&lt;br /&gt;
'''reopen_log'''&lt;br /&gt;
:在日志文件改名之后重新打开它们. 如果在调用此命令之前旧文件没有被改名, 它们自动改名为 &amp;quot;*-old.log&amp;quot;. 见 [[Ejabberd2:安装和操作指南#日志文件|7.1]] 节. &lt;br /&gt;
'''backup ejabberd.backup'''&lt;br /&gt;
:存储内部的 Mnesia 数据库到一个二进制备份文件. &lt;br /&gt;
'''restore ejabberd.backup'''&lt;br /&gt;
:立刻从一个二进制文件恢复内部的 Mnesia 数据库. 如果你有一个很大的数据库，这将消耗很多内存, 所以最好使用 install_fallback. &lt;br /&gt;
'''install_fallback ejabberd.backup'''&lt;br /&gt;
:安装成fallback的二进制备份文件: 它将在下一次ejabberd启动的时候被用于恢复数据库. 这意味着, 在运行这个命令之后, 你不得不重启 ejabberd. 这个命令比restore需要更少的内存. &lt;br /&gt;
'''dump ejabberd.dump'''&lt;br /&gt;
:Dump内部的 Mnesia 数据库到一个文本文件 dump. &lt;br /&gt;
'''load ejabberd.dump'''&lt;br /&gt;
:立刻从一个文本文件dump恢复. 这不建议用于大数据库, 因为它将消耗很多时间, 内存和cpu. 在那种情况下，它适合使用 backup 和 install_fallback. &lt;br /&gt;
'''import_piefxis, export_piefxis, export_piefxis_host'''&lt;br /&gt;
:这些选项可被用于迁移帐户，使用 [http://xmpp.org/extensions/xep-0227.html XEP-0227] 格式的 XML文件 从/到 另外一个 Jabber/XMPP 服务器或转移一个虚拟主机的用户到另一个 ejabberd 安装环境. 也见于 [https://support.process-one.net/doc/display/MESSENGER/ejabberd+migration+kit ejabberd迁移工具]. &lt;br /&gt;
'''import_file, import_dir'''&lt;br /&gt;
:这些选项可被用于迁移使用jabberd1.4格式的XML文件的帐户, 从其他 Jabber/XMPP 服务器. 已经有 [http://www.ejabberd.im/migrate-to-ejabberd 从其他软件迁移到ejabberd]的教程. &lt;br /&gt;
'''delete_expired_messages'''&lt;br /&gt;
:这个选项可被用于删除旧的离线消息. 当离线消息数量非常高的时候有用. &lt;br /&gt;
'''delete_old_messages days'''&lt;br /&gt;
:删除指定天数之前的离线消息. &lt;br /&gt;
'''register user host password'''&lt;br /&gt;
:在那个域以给定的密码注册一个帐号. &lt;br /&gt;
'''unregister user host'''&lt;br /&gt;
:注销给定帐号.&lt;br /&gt;
&lt;br /&gt;
====以AccessCommands限制执行====&lt;br /&gt;
&lt;br /&gt;
前端可能被配置成限制访问特定的命令. 在那种情况下, 必须提供验证信息. 在每个前端，AccessCommands 选项被定义在不同的地方. 但是所有情况下这个选项的语法都是相同的:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
AccessCommands = [ {Access, CommandNames, Arguments}, ...]&lt;br /&gt;
Access = atom()&lt;br /&gt;
CommandNames = all | [CommandName]&lt;br /&gt;
CommandName = atom()&lt;br /&gt;
Arguments = [ {ArgumentName, ArgumentValue}, ...]&lt;br /&gt;
ArgumentName = atom()&lt;br /&gt;
ArgumentValue = any()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
缺省值是不定义任何限制: []. 当执行一个命令时提供验证信息, 为一个被允许执行相应命令的本地XMPP帐号的 Username, Hostname 和 Password . 这意味着这个帐号必须在本地ejabberd已经注册, 因为这个信息将被验证. 可能提供纯文本密码或它的 MD5 哈希值.&lt;br /&gt;
&lt;br /&gt;
当定义了一个或多个访问限制，并且提供了验证信息, 每个限制被验证直到某人完全符合: 这个帐号和 Access rule匹配, 命令名字列于 CommandNames 之中, 并且提供的参数和Arguments不抵触.&lt;br /&gt;
&lt;br /&gt;
以下例子用来理解这个语法, 让我们假设那些选项:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{hosts, [&amp;quot;example.org&amp;quot;]}.&lt;br /&gt;
{acl, bots, {user, &amp;quot;robot1&amp;quot;, &amp;quot;example.org&amp;quot;}}.&lt;br /&gt;
{access, commaccess, [{allow, bots}]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
访问限制的列表只允许 robot1@example.org 执行所有命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[{commaccess, all, []}]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
看看另一个限制列表 (相应的 ACL 和 ACCESS 没有显式):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
 %% 这个 bot 能执行所有命令:&lt;br /&gt;
 {bot, all, []},&lt;br /&gt;
 %% 这个 bot 只能执行命令 'dump'. 不限制参数:&lt;br /&gt;
 {bot_backups, [dump], []}&lt;br /&gt;
 %% 这个 bot 可执行所有命令,&lt;br /&gt;
 %% 但是如果使用 'host' 参数, 它必须是 &amp;quot;example.org&amp;quot;:&lt;br /&gt;
 {bot_all_example, all, [{host, &amp;quot;example.org&amp;quot;}]},&lt;br /&gt;
 %% 这个 bot 只能执行命令 'register',&lt;br /&gt;
 %% 并且如果使用参数 'host' , 它必须是 &amp;quot;example.org&amp;quot;:&lt;br /&gt;
 {bot_reg_example, [register], [{host, &amp;quot;example.org&amp;quot;}]},&lt;br /&gt;
 %% 这个 bot 能执行命令 'register' 和 'unregister',&lt;br /&gt;
 %% 如果使用参数 host , 它必须是 &amp;quot;test.org&amp;quot;:&lt;br /&gt;
 {_bot_reg_test, [register, unregister], [{host, &amp;quot;test.org&amp;quot;}]}&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Web管理===&lt;br /&gt;
&lt;br /&gt;
ejabberd Web管理允许使用web浏览器管理大部分ejabberd.&lt;br /&gt;
&lt;br /&gt;
这个功能缺省是激活的: 一个使用选项 web_admin (见 [[Ejabberd2:安装和操作指南#监听端口|3.1.3]] 节)的 ejabberd_http 监听者被包含在监听的端口里. 然后你可以在你中意的wen浏览器里打开 http://server:port/admin/ . 你将被要求键入一个拥有管理员权限的ejabberd用户的 username (全 Jabber ID) 和 password . 在验证之后你将看到一个页面类似 figure 4.1.&lt;br /&gt;
    &lt;br /&gt;
:''webadmmain.png''&lt;br /&gt;
:''Figure 4.1: Top page from the Web Admin''&lt;br /&gt;
&lt;br /&gt;
这里你可以编辑访问限制, 管理用户, 建立备份, 管理数据库, 允许/禁止 监听的端口, 查看服务器统计数据,…&lt;br /&gt;
&lt;br /&gt;
access rule 配置决定那些帐号可以访问Web管理以及修改它. access rule webadmin_view 仅被赋予查看权限: 那些帐号能以只读方式浏览Web管理.&lt;br /&gt;
&lt;br /&gt;
示例配置:&lt;br /&gt;
&lt;br /&gt;
* 你可以把Web管理伺服于和HTTP 轮询界面相同的端口. 在这个了例子里你应该把你的web浏览器指向 http://example.org:5280/admin/ 来管理所有虚拟主机或指向 http://example.org:5280/admin/server/example.com/ 来管理虚拟主机 example.com. 在你访问Web管理之前你需要键入从一个被允许配置ejabberd的已注册的用户那里得到的 username, JID 和 password . 在这个例子里你可键入 username ‘admin@example.net’ 来管理所有虚拟主机 (第一个 URL). 如果你以‘admin@example.com’登录到http://example.org:5280/admin/server/example.com/ ，你只能管理虚拟主机 example.com. 帐号‘reviewer@example.com’可以只读模式浏览虚拟主机.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {acl, admins, {user, &amp;quot;admin&amp;quot;, &amp;quot;example.net&amp;quot;}}.&lt;br /&gt;
      {host_config, &amp;quot;example.com&amp;quot;, [{acl, admins, {user, &amp;quot;admin&amp;quot;, &amp;quot;example.com&amp;quot;}}]}.&lt;br /&gt;
      {host_config, &amp;quot;example.com&amp;quot;, [{acl, viewers, {user, &amp;quot;reviewer&amp;quot;, &amp;quot;example.com&amp;quot;}}]}.&lt;br /&gt;
&lt;br /&gt;
      {access, configure, [{allow, admins}]}.&lt;br /&gt;
      {access, webadmin_view, [{allow, viewers}]}.&lt;br /&gt;
&lt;br /&gt;
      {hosts, [&amp;quot;example.org&amp;quot;]}.&lt;br /&gt;
&lt;br /&gt;
      {listen,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {5280, ejabberd_http, [http_poll, web_admin]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 因为安全的原因, 你可以在一个安全的连接上伺服Web管理, 在一个不同于HTTP轮询接口的端口上, 并把它绑定到内部的局域网IP. 这个Web管理将只能被浏览器从https://192.168.1.1:5282/admin/ 访问:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
      {hosts, [&amp;quot;example.org&amp;quot;]}.&lt;br /&gt;
&lt;br /&gt;
      {listen,&lt;br /&gt;
       [&lt;br /&gt;
        ...&lt;br /&gt;
        {5280, ejabberd_http, [&lt;br /&gt;
                               http_poll&lt;br /&gt;
                              ]},&lt;br /&gt;
        {{5282, &amp;quot;192.168.1.1&amp;quot;}, ejabberd_http, [&lt;br /&gt;
                                                web_admin,&lt;br /&gt;
                                                tls, {certfile, &amp;quot;/usr/local/etc/server.pem&amp;quot;}&lt;br /&gt;
                                               ]},&lt;br /&gt;
        ...&lt;br /&gt;
       ]}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在ejabberd Web管理 特定的页面包含了一个连接到 ejabberd安装和操作指南 的相关章节. 为了显式这些链接, 本指南的一个 HTML 格式的拷贝必须安装在该系统上. 该文件缺省的放在 &amp;quot;/share/doc/ejabberd/guide.html&amp;quot;. 该文档的目录可以被环境变量 EJABBERD_DOC_PATH 指定. 参见 [[Ejabberd2:安装和操作指南#Erlang运行时系统|4.1.2]] 节.&lt;br /&gt;
&lt;br /&gt;
===特设命令===&lt;br /&gt;
&lt;br /&gt;
如果你激活了 mod_configure 和 mod_adhoc, 你可以使用一个 XMPP 客户端在 ejabberd执行很多管理任务. 该客户端必须支持 Ad-Hoc Commands ([http://xmpp.org/extensions/xep-0050.html XEP-0050]), 而你必须以一个拥有适当权限的帐号登录到该 XMPP 服务器.&lt;br /&gt;
&lt;br /&gt;
===修改计算机主机名===&lt;br /&gt;
&lt;br /&gt;
ejabberd使用分布式的 Mnesia 数据库. 作为分布式数据库, Mnesia 强制它的文件一致性, 所以它在它里面存储Erlang节点名 (见 [[Ejabberd2:安装和操作指南#Erlang节点名|5.4]] 节). 一个Erlang节点的名字包含了该计算机的hostname. 所以, 如果你修改ejabberd运行的机器的名字，或当你移动ejabberd到一个不同的机器上，那么Erlang节点名也修改了.&lt;br /&gt;
&lt;br /&gt;
你有两个办法在一个新节点名的 ejabberd 上使用旧的 Mnesia 数据库: 把旧节点名放入 ejabberdctl.cfg, 或转换数据库到为新节点名.&lt;br /&gt;
&lt;br /&gt;
那些例子步骤将备份, 转换并装载 Mnesia 数据库. 你需要要么有旧的 Mnesia spool 目录，要么有一个 Mnesia 的备份. 如果你已经有一个旧的数据库的备份文件, 你可以直接去步骤 5. 你也需要知道旧节点名和新节点名. 如果你不知道它们, 执行ejabberdctl或在ejabberd 日志文件里查找它们.&lt;br /&gt;
&lt;br /&gt;
在开始之前, 设置一些变量:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
OLDNODE=ejabberd@oldmachine&lt;br /&gt;
NEWNODE=ejabberd@newmachine&lt;br /&gt;
OLDFILE=/tmp/old.backup&lt;br /&gt;
NEWFILE=/tmp/new.backup&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
1. 强制以旧节点名启动 ejabberd :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ejabberdctl --node $OLDNODE start&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. 生成一个备份文件:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ejabberdctl --node $OLDNODE backup $OLDFILE&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. 停止旧节点:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ejabberdctl --node $OLDNODE stop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. 确保在 Mnesia spool 目录没有文件 . 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      mkdir /var/lib/ejabberd/oldfiles&lt;br /&gt;
      mv /var/lib/ejabberd/*.* /var/lib/ejabberd/oldfiles/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. 启动 ejabberd. 不需要再指定任何节点名:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ejabberdctl start&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. 转换备份到新节点名:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ejabberdctl mnesia_change_nodename $OLDNODE $NEWNODE $OLDFILE $NEWFILE&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7. 安装备份文件作为一个fallback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ejabberdctl install_fallback $NEWFILE&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
8. 停止 ejabberd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ejabberdctl stop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:你可能在日志文件看到一个错误信息, 这是正常的, 不要担心:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
      Mnesia(ejabberd@newmachine):&lt;br /&gt;
      ** ERROR ** (ignoring core)&lt;br /&gt;
      ** FATAL ** A fallback is installed and Mnesia must be restarted.&lt;br /&gt;
        Forcing shutdown after mnesia_down from ejabberd@newmachine...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
9. 现在你可以最后启动 ejabberd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      ejabberdctl start&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
10. 检查是否旧数据库的信息可用: accounts, rosters... 完成之后, 记住从公共目录删除临时备份文件.&lt;br /&gt;
&lt;br /&gt;
==ejabberd安全==&lt;br /&gt;
===防火墙设置===&lt;br /&gt;
&lt;br /&gt;
当你配置防火墙的时候，你需要注意以下 TCP 端口: &lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!端口 !!描述&lt;br /&gt;
|-&lt;br /&gt;
|5222 ||用于 Jabber/XMPP 客户端连接的标准端口, 纯文本或 STARTTLS.&lt;br /&gt;
|-&lt;br /&gt;
|5223 ||Jabber 客户端使用旧的 SSL 方法连接的标准端口 .&lt;br /&gt;
|-&lt;br /&gt;
|5269 ||用于 Jabber/XMPP 服务器连接的标准端口.&lt;br /&gt;
|-&lt;br /&gt;
|4369 ||EPMD ([[Ejabberd2:安装和操作指南#EPMD|5.2]] 节) 监听Erlang节点名请求.&lt;br /&gt;
|-&lt;br /&gt;
|端口范围 ||用于两个Erlang节点之间的连接. 这个范围是可配置的(见 [[Ejabberd2:安装和操作指南#EPMD|5.2]] 节).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===epmd===&lt;br /&gt;
&lt;br /&gt;
[http://www.erlang.org/doc/man/epmd.html epmd (Erlang端口映射守候进程)] 是一个包含在 Erlang/OTP 里的小的名字服务器，并且在建立分布式 Erlang 通讯时被 Erlang 程序使用. ejabberd 需要 epmd 来使用 ejabberdctl 并且使用集群的ejabberd 节点时也需要它. 这个小的程序是由Erlang自动启动的, 并且永不停止. 如果 ejabberd 停止了, 并且没有任何其他 Erlang 程序运行在系统上, 如果你想的话可以安全地停止 epmd.&lt;br /&gt;
&lt;br /&gt;
ejabberd 运行在一个Erlang节点内部. 为了和 ejabberd 通讯, 脚本 ejabberdctl 启动一个新的 Erlang 节点并连接到这个运行着 ejabberd 的Erlang节点. 为了这个通讯能工作, epmd 必须运行和在端口4369监听名字请求. 你应该在防火墙以这种方式禁止端口4369，即只允许你机器上的程序访问它.&lt;br /&gt;
&lt;br /&gt;
如果你建立了一个许多 ejabberd 实例的集群, 每个 ejabberd 实例被称为一个 ejabberd 节点. 那些 ejabberd 节点使用一个特别的 Erlang 通讯方法来建立集群, 那么 EPMD 再次需要监听端口 4369. 所以, 如果你计划计建立一个 ejabberd 节点的集群，你必须为这个集群涉及的机器打开端口 4369. 记住禁止这个端口使得它无法从互联网访问到.&lt;br /&gt;
&lt;br /&gt;
一旦一个Erlang节点使用EPMD和端口4369解析了另一个Erlang节点的节点名, 节点之间就直接通讯. 在这个情况下使用的端口缺省是随机的, 但是可以在文件 ejabberdctl.cfg里配置. Erlang命令行参数被内部使用, 例如:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
erl ... -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Erlang Cookie===&lt;br /&gt;
&lt;br /&gt;
Erlang cookie 是一个数字和字母组成的字符串. 一个Erlang节点在启动时从命令行参数 -setcookie 读取cookie. 如果没有指定, 则从 $HOME/.erlang.cookie 读取cookie 文件. 如果这个文件不存在, 它会被立刻以一个随机的cookie建立. 两个Erlang节点只有它们有相同的cookie才会通讯 . 在Erlang节点上设置一个cookie允许你结构化你的Erlang网络并定义哪个节点被允许连接到哪个.&lt;br /&gt;
&lt;br /&gt;
感谢Erlang cookies, 你可以阻止对Erlang节点的错误访问, 例如当同一台机器上有许多Erlang节点运行不同程序的时候.&lt;br /&gt;
&lt;br /&gt;
设置一个安全cookie是一个简单的方法来增加非法访问你的Erlang节点的困难度. 然而, 对于阻止对Erlang节点的未授权访问或侵扰，cookie系统不是最终有效的. Erlang节点之间的通讯是未加密的, 所以 cookie 可能被网络上的探针读取. 推荐使得Erlang更加安全的方法是禁止端口4369.&lt;br /&gt;
&lt;br /&gt;
===Erlang节点名===&lt;br /&gt;
&lt;br /&gt;
一个Erlang节点可以拥有一个节点名. 这个名字可能很短 (如果用命令行参数 -sname 指定) 或很长 (如果用参数 -name 指定). 以 -sname 启动一个Erlang节点限制Erlang节点和LAN之间的通讯.&lt;br /&gt;
&lt;br /&gt;
使用选项 -sname 而不是 -name ，是一个简单增加对你的Erlang节点的未授权访问难度的方法. 然而, 对于阻止对Erlang节点的未授权访问或侵扰，它不是最终有效的. 因为有可能伪装你在另一个网络里使用一个修改过的 Erlang epmd. 推荐使得Erlang更加安全的方法是禁止端口4369.&lt;br /&gt;
&lt;br /&gt;
===敏感文件安全===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ejabberd在文件系统里存储敏感数据要么使用纯文本要么是二进制文件. 文件系统许可应被设置为只允许适当的用户读, 写和执行那些文件和目录.&lt;br /&gt;
&lt;br /&gt;
'''ejabberd configuration file: /etc/ejabberd/ejabberd.cfg'''&lt;br /&gt;
:包含外部组件的管理员的 JID 和密码. 备份文件可能也包含这个信息, 所以整个 /etc/ejabberd/ 目录的安全是必要的. &lt;br /&gt;
'''ejabberd service log: /var/log/ejabberd/ejabberd.log'''&lt;br /&gt;
:包含客户端的IP地址. 如果 loglevel 设为 5, 它包含全部的会话和密码. 如果使用了一个 logrotate 系统, 可能有好几个日志文件拥有类似的信息, 所以整个 /var/log/ejabberd/ 目录的安全是必要的. &lt;br /&gt;
'''Mnesia database spool files in /var/lib/ejabberd/'''&lt;br /&gt;
:这个文件存储二进制数据, 但是一些部分仍是可读的. 这个文件由 Mnesia 生成并且它们的许可不能被直接设置, 所以整个 /var/lib/ejabberd/ 目录的安全是必要的. &lt;br /&gt;
'''Erlang cookie file: /var/lib/ejabberd/.erlang.cookie'''&lt;br /&gt;
:见 [[Ejabberd2:安装和操作指南#Erlang Cookie|5.3]] 节.&lt;br /&gt;
&lt;br /&gt;
==集群==&lt;br /&gt;
===如何工作===&lt;br /&gt;
&lt;br /&gt;
一个XMPP域是由一个或多个ejabberd节点伺服的. 这些节点可能运行在通过网络连接的不同的机器上. 它们都必须有能力连接到所有其他节点的4369端口, 并且必须有相同的 magic cookie (见 Erlang/OTP 文档, 换句话说，在所有节点上，文件 ~ejabberd/.erlang.cookie 必须是相同的 ). 这是必须的，因为所有节点交换关于已连接的用户, s2s连接, 已注册的服务, 等等…信息.&lt;br /&gt;
&lt;br /&gt;
每个 ejabberd 节点有意下模块:&lt;br /&gt;
&lt;br /&gt;
* router,&lt;br /&gt;
* local router,&lt;br /&gt;
* session manager,&lt;br /&gt;
* s2s manager. &lt;br /&gt;
&lt;br /&gt;
====Router====&lt;br /&gt;
&lt;br /&gt;
这个模块是每个节点的XMPP包的主router. 它基于它们的目标域来路由它们. 它使用一个全局路由表. 在这个路由表里搜索到包的目的地的域, 并且如果找到, 这个包就被路由到适当的进程. 如果没找到, 它被送到 s2s manager.&lt;br /&gt;
&lt;br /&gt;
====Local Router====&lt;br /&gt;
&lt;br /&gt;
这个模块路由那些目的域等于服务器的主机名之一的包. 如果目的JID有一个非空的 user 部分, 它路由到 session manager, 反之则它的处理依赖于它的内容.&lt;br /&gt;
&lt;br /&gt;
====Session Manager====&lt;br /&gt;
&lt;br /&gt;
这个模块路由包到本地用户. 它通过一个出席信息表查找一个包必须被发送给哪个用户资源. 然后该包要么路由到适当的 c2s 进程, 要么存储在离线存储 offline storage, 或弹回.&lt;br /&gt;
&lt;br /&gt;
====s2s Manager====&lt;br /&gt;
&lt;br /&gt;
这个模块路由包到其他 XMPP 服务器. 首先, 它检查是否已存在一个从该包的源域到目的域的s2s连接. 如果有, s2s manager 路由这个包到伺服这个连接的进程, 反之打开一个新的连接.&lt;br /&gt;
&lt;br /&gt;
===集群配置===&lt;br /&gt;
&lt;br /&gt;
假定你已经在一个机器named(第一个)上配置了 ejabberd , 并且你需要配置另外一个来做一个 ejabberd 集群. 那么按以下步骤做:&lt;br /&gt;
&lt;br /&gt;
1. 从第一台机器拷贝 ~ejabberd/.erlang.cookie 文件到第二台机器.&lt;br /&gt;
&lt;br /&gt;
:(或者) 你也可以增加‘-setcookie content_of_.erlang.cookie’选项到以下所有‘erl’ 命令.&lt;br /&gt;
&lt;br /&gt;
2. 在第二台机器上，在ejabberd工作目录中，以 ejabberd 守候进程用户运行以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      erl -sname ejabberd \&lt;br /&gt;
          -mnesia dir '&amp;quot;/var/lib/ejabberd/&amp;quot;' \&lt;br /&gt;
          -mnesia extra_db_nodes &amp;quot;['ejabberd@first']&amp;quot; \&lt;br /&gt;
          -s mnesia&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:这将启动 Mnesia 服务于和 ejabberd@first 相同的数据库. 你可以运行命令 ‘mnesia:info().’检查它. 你应该看到许多远程表和行，类似以下:&lt;br /&gt;
&lt;br /&gt;
:注意: 在你的系统里 Mnesia 目录可能是不同的. 要知道 ejabberd 期望在哪里找到 Mnesia 的缺省安装, 不带参数调用 ejabberdctl 然后它将显式一些帮助, 包括 Mnesia database spool 目录.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      running db nodes   = [ejabberd@first, ejabberd@second]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. 现在在相同的‘erl’会话下运行以下命令:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
      mnesia:change_table_copy_type(schema, node(), disc_copies).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:这将为该数据库建立本地磁盘存储.&lt;br /&gt;
&lt;br /&gt;
:(或者) 在第二个节点通过Web管理修改scheme表的存储类型为‘RAM and disc copy’.&lt;br /&gt;
&lt;br /&gt;
4. 现在你可以增加更多表的复制到这个节点 ，使用‘mnesia:add_table_copy’ 或 ‘mnesia:change_table_copy_type’如上 (只是把 ‘schema’ 替换成其他表名，并且 ‘disc_copies’可以被替换成‘ram_copies’ 或 ‘disc_only_copies’).&lt;br /&gt;
&lt;br /&gt;
:哪个表被复制，依赖于你的需要, 你可以从‘mnesia:info().’命令得到一些提示, 通过查看每个位于 ’first’的表的大小和缺省的存储类型.&lt;br /&gt;
&lt;br /&gt;
复制一个表使得这个节点的这个表的查询更加快速. 写入, 另一方面, 将更慢. 而且当然如果复制之一的机器挂了, 其他复制将被使用.&lt;br /&gt;
&lt;br /&gt;
:看一下 [http://www.erlang.org/doc/apps/mnesia/Mnesia_chap5.html#5.3 Mnesia用户指南的 5.3 节(表 片段)]将有所帮助.&lt;br /&gt;
&lt;br /&gt;
: (或者) 同之前的条目, 但用于不同的表.&lt;br /&gt;
&lt;br /&gt;
5. 运行‘init:stop().’ 或只是 ‘q().’ 退出 Erlang shell. 这可能要花些时间，如果 Mnesia 还没有从first传输和处理完所有数据.&lt;br /&gt;
&lt;br /&gt;
6. 现在在第二台机器上使用和第一台机器类似的配置运行 ejabberd: 你可能不需要重复‘acl’ 和 ‘access’ 选项，因为它们将从第一台机器获得; 并且 mod_irc 只应该在集群里的一台机器上激活. &lt;br /&gt;
&lt;br /&gt;
你可以在其他机器上重复这些步骤来服务于这个域.&lt;br /&gt;
&lt;br /&gt;
===服务负载均衡===&lt;br /&gt;
====组件负载均衡====&lt;br /&gt;
====域负载均衡机制====&lt;br /&gt;
&lt;br /&gt;
ejabberd包含了一个机制来对插入一个ejabberd集群的组件进行负载均衡. 它意味着你可以在每一个ejabberd集群插入相同组件的一个或多个实例并且流量将自动分布.&lt;br /&gt;
&lt;br /&gt;
缺省的分布式机制尝试递送到组件的一个本地实例. 如果有多个本地实例可用, 随机地选取一个实例. 如果没有本地实例可用, 随机选取一个远程组件实例.&lt;br /&gt;
&lt;br /&gt;
如果你需要一个不同的行为, 你可以通过选项 domain_balancing 修改负载均衡行为. 这个选项的语法如下:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{domain_balancing, &amp;quot;component.example.com&amp;quot;, BalancingCriteria}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
多个负载均衡标准可用:&lt;br /&gt;
&lt;br /&gt;
* destination: 使用包的to属性的全JID.&lt;br /&gt;
* source: 使用包的from属性的全JID.&lt;br /&gt;
* bare_destination: 使用包的to属性的纯JID(没有资源).&lt;br /&gt;
* bare_source: 使用包的from属性的纯JID(没有资源). &lt;br /&gt;
&lt;br /&gt;
如果对应标准的这个值是相同的, 则集群中相同的组件实例将被使用.&lt;br /&gt;
&lt;br /&gt;
====负载均衡水桶====&lt;br /&gt;
&lt;br /&gt;
当一个给定的组件有失败的风险的时候, 域均衡可能导致服务麻烦. 如果一个组件失败了，服务将无法正确工作，除非会话被重新均衡了.&lt;br /&gt;
&lt;br /&gt;
在这种情况下, 最好限制这个问题在由失败组件处理的这些会话. 这就是 domain_balancing_component_number 选项所做的, 使负载均衡机制不动态化, 而是粘在固定数目的组件实例上.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{domain_balancing_component_number, &amp;quot;component.example.com&amp;quot;, Number}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==调试==&lt;br /&gt;
===日志文件===&lt;br /&gt;
&lt;br /&gt;
一个ejabberd节点写两个日志文件:&lt;br /&gt;
&lt;br /&gt;
'''ejabberd.log'''&lt;br /&gt;
:ejabberd 服务日志, 由 ejabberd 节点汇报的消息&lt;br /&gt;
'''erlang.log'''&lt;br /&gt;
:Erlang/OTP 系统日志, 由 Erlang/OTP 使用 SASL (系统架构支持库) 汇报的消息&lt;br /&gt;
&lt;br /&gt;
选项 loglevel 修改文件 ejabberd.log 的详细程度. 语法是:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{loglevel, Level}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
可能的 Level 有:&lt;br /&gt;
&lt;br /&gt;
'''0'''&lt;br /&gt;
:没有ejabberd日志 (不推荐) &lt;br /&gt;
'''1'''&lt;br /&gt;
:紧急&lt;br /&gt;
'''2'''&lt;br /&gt;
:错误&lt;br /&gt;
'''3'''&lt;br /&gt;
:警告&lt;br /&gt;
'''4'''&lt;br /&gt;
:信息&lt;br /&gt;
'''5'''&lt;br /&gt;
:调试&lt;br /&gt;
&lt;br /&gt;
例如, 缺省配置为:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{loglevel, 4}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
日志文件持续增长, 所以推荐定期流转. 为了流转日志文件, 重命名这个文件然后重新打开它们. ejabberdctl命令reopen-log (请参考 [[Ejabberd2:安装和操作指南# ejabberdctl命令|4.1.1]] 节) 重新打开日志文件, 同时也重命名旧文件，如果你不重命名它们的话.&lt;br /&gt;
&lt;br /&gt;
===调试控制台===&lt;br /&gt;
&lt;br /&gt;
调试控制台是连接到一个已运行的 ejabberd 服务器的 Erlang shell. 使用这个 Erlang shell, 一个有经验的管理员可以执行复杂的任务.&lt;br /&gt;
&lt;br /&gt;
这个 shell 给予对ejabberd 服务器的完全控制, 所以使用它要非常小心. 在文章 [http://www.ejabberd.im/interconnect-erl-nodes Erlang节点的互连] 里有一些简单和安全的例子&lt;br /&gt;
&lt;br /&gt;
要退出这个shell, 关闭窗口或键入: control+c control+c.&lt;br /&gt;
&lt;br /&gt;
===Watchdog警告===&lt;br /&gt;
&lt;br /&gt;
ejabberd包含了一个看门狗 watchdog 机制，当找出和内存使用有关的问题时，对开发者可能有用. 如果ejabberd服务器的一个进程消耗了超过配置阀值的内存, 一个消息将被发送到ejabberd配置文件中选项 watchdog_admins 定义的 XMPP 帐号.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{watchdog_admins, [JID, ...]}.'''&lt;br /&gt;
&lt;br /&gt;
消耗的内存以words衡量: 一个word在32位系统上是4字节bytes, 在64位系统上是8字节bytes. 这个阀值缺省是 1000000 words. 这个值可以用选项 watchdog_large_heap来配置, 或在一个会话中使用watchdog警报机器人.&lt;br /&gt;
&lt;br /&gt;
语法是:&lt;br /&gt;
&lt;br /&gt;
'''{watchdog_large_heap, Number}.'''&lt;br /&gt;
&lt;br /&gt;
示例配置:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{watchdog_admins, [&amp;quot;admin2@localhost&amp;quot;, &amp;quot;admin2@example.org&amp;quot;]}.&lt;br /&gt;
{watchdog_large_heap, 30000000}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
要移除watchdog管理员, 在选项里移除. 为了移除所有watchdog管理员, 设置该选项为空列表:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
{watchdog_admins, []}.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==附录 A 国际化和本地化==&lt;br /&gt;
&lt;br /&gt;
ejabberd的源码支持本地化. 翻译者可编辑 [http://www.gnu.org/software/gettext/ gettext] .po 文件，使用任何可用的软件 (KBabel, Lokalize, Poedit...) 或一个简单的文本编辑器.&lt;br /&gt;
&lt;br /&gt;
接着gettext用来提取, 更新和导出那些 .po 文件成为能被ejabberd读取的 .msg 格式. 为执行那些管理任务, 在 src/ 目录执行 ''make translations''. 可翻译的字符串被从源码提取出来生成文件 ejabberd.pot. 这个文件合并每个 .po 文件来生成更新的 .po 文件. 最后那些 .po 文件被导出成 .msg 文件, 那是个容易被 ejabberd 读取的格式.&lt;br /&gt;
&lt;br /&gt;
所有內建的模块都支持内部的IQ queries的xml:lang 属性 . Figure A.1, 例如, 展示了应答以下 query:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iq id='5'&lt;br /&gt;
    to='example.org'&lt;br /&gt;
    type='get'&lt;br /&gt;
    xml:lang='ru'&amp;gt;&lt;br /&gt;
  &amp;lt;query xmlns='http://jabber.org/protocol/disco#items'/&amp;gt;&lt;br /&gt;
&amp;lt;/iq&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    discorus.png&lt;br /&gt;
    Figure A.1: Service Discovery when xml:lang=’ru’&lt;br /&gt;
&lt;br /&gt;
Web管理也支持 Accept-Language HTTP 头.&lt;br /&gt;
&lt;br /&gt;
    webadmmainru.png&lt;br /&gt;
    Figure A.2: Web Admin showing a virtual host when the web browser provides the HTTP header ‘Accept-Language: ru’&lt;br /&gt;
&lt;br /&gt;
==附录 B 发行备注==&lt;br /&gt;
&lt;br /&gt;
发行备注在 [http://www.process-one.net/en/ejabberd/release_notes/ ejabberd主页]&lt;br /&gt;
&lt;br /&gt;
==附录 C 鸣谢==&lt;br /&gt;
&lt;br /&gt;
感谢所有对本指南有贡献的人:&lt;br /&gt;
&lt;br /&gt;
* Alexey Shchepin (xmpp:aleksey@jabber.ru)&lt;br /&gt;
* Badlop (xmpp:badlop@jabberes.org)&lt;br /&gt;
* Evgeniy Khramtsov (xmpp:xram@jabber.ru)&lt;br /&gt;
* Florian Zumbiehl (xmpp:florz@florz.de)&lt;br /&gt;
* Michael Grigutsch (xmpp:migri@jabber.i-pobox.net)&lt;br /&gt;
* Mickael Remond (xmpp:mremond@process-one.net)&lt;br /&gt;
* Sander Devrieze (xmpp:s.devrieze@gmail.com)&lt;br /&gt;
* Sergei Golovan (xmpp:sgolovan@nes.ru)&lt;br /&gt;
* Vsevolod Pelipas (xmpp:vsevoload@jabber.ru)&lt;br /&gt;
&lt;br /&gt;
==附录 D 版权信息==&lt;br /&gt;
&lt;br /&gt;
略...&lt;br /&gt;
&lt;br /&gt;
Ejabberd Installation and Operation Guide.&lt;br /&gt;
Copyright © 2003 — 2010 ProcessOne&lt;br /&gt;
&lt;br /&gt;
This document is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.&lt;br /&gt;
&lt;br /&gt;
This document is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.&lt;br /&gt;
&lt;br /&gt;
You should have received a copy of the GNU General Public License along with this document; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.&lt;/div&gt;</summary>
		<author><name>Terence lee100</name></author>	</entry>

	</feed>