rfc 6120 為ietf提出的替換原有xmpp/jabber 核心協議frc 3920
### 概述
可擴展的消息和出席信息協議(XMPP)是一個可擴展標記語言[XML](http://wiki.jabbercn.org/RFC6120#XML "RFC6120")應用,讓任何兩個或多個網絡實體之間進行結構化和可擴展的準實時信息交流. 本文定義了XMPP的核心協議方法: XML流的配置和解除, 通道加密, 驗證, 錯誤處理, 以及消息通訊基礎, 網絡可用性 ("presence"), 和 請求-應答 交互.
### 歷史
XMPP的基本語法和語義最開始是由Jabber開源社區開發的, 主要是在1999年. 2002年, 根據?[IMP?REQS](http://wiki.jabbercn.org/RFC6120#IMP.E2.80.91REQS "RFC6120")?,XMPP工作組被允許基于Jabber協議開發一個適合IETF的即時消息和出席信息技術. 到了2004年10月, 發布了?[RFC3920](http://wiki.jabbercn.org/RFC3920 "RFC3920")?和?[RFC3921](http://wiki.jabbercn.org/RFC3921 "RFC3921")?, 意味著那時候XMPP的主要定義完成了.
從2004年開始,互聯網社區已經獲得了廣泛的XMPP實現和布署經驗, 包括XMPP標準基金會(XSF)主持下開展的正式的互操作性測試. 本文全面整合了從軟件開發者和XMPP服務提供者得到的反饋, 包含了一系列向后兼容的修改,?結果是, 本文反映了互聯網社區對于XMPP1.0核心功能的初步共識, 因此廢止了[RFC 3920](http://tools.ietf.org/html/rfc3920 "http://tools.ietf.org/html/rfc3920").
### 功能匯總
這個不規范的章節提供了一個方便開發者的XMPP功能匯總; 接下來的其他章節則是XMPP的規范定義.
XMPP的目標是允許兩個(或多個)實體通過網絡來交換相關的小件結構化數據(所謂"XML節"). XMPP典型地使用分布式的 客戶端-服務器 體系結構來實現, 這里客戶端需要連接到一個服務器以獲得對網絡的訪問,從而被允許和其他實體(可能在其他服務器上)交換XML節. 一個客戶端連接到一個服務器,交換XML節,以及結束連接,這樣的流程如下:
1. 確定要連接的IP地址和端口號, 典型的做法是對一個合格的域名做出解析(?[3.2](http://wiki.jabbercn.org/RFC6120#.E5.90.88.E6.A0.BC.E5.9F.9F.E5.90.8D.E7.9A.84.E8.A7.A3.E6.9E.90 "RFC6120")?)
1. 打開一個傳輸控制協議?[TCP](http://wiki.jabbercn.org/RFC6120#TCP "RFC6120")?連接
1. 通過TCP打開一個XML流?[4.2](http://wiki.jabbercn.org/RFC6120#.E6.89.93.E5.BC.80.E4.B8.80.E4.B8.AA.E6.B5.81 "RFC6120")
1. 握手最好使用傳輸層安全性?[TLS](http://wiki.jabbercn.org/RFC6120#TLS "RFC6120")?來進行通道加密(?[5](http://wiki.jabbercn.org/RFC6120#STARTTLS.E6.8F.A1.E6.89.8B "RFC6120")?)
1. 使用簡單驗證和安全層?[SASL](http://wiki.jabbercn.org/RFC6120#SASL "RFC6120")?機制來驗證 (?[6](http://wiki.jabbercn.org/RFC6120#SASL.E6.8F.A1.E6.89.8B "RFC6120")?)
1. 綁定一個資源到這個留上 (?[7](http://wiki.jabbercn.org/RFC6120#.E8.B5.84.E6.BA.90.E7.BB.91.E5.AE.9A "RFC6120")?)
1. 和其他網絡上的實體交換不限數量的XML節(?[8](http://wiki.jabbercn.org/RFC6120#XML.E8.8A.82 "RFC6120")?)
1. 關閉XML流 (?[4.4](http://wiki.jabbercn.org/RFC6120#.E5.85.B3.E9.97.AD.E4.B8.80.E4.B8.AA.E6.B5.81 "RFC6120")?)
1. 關閉TCP連接
在XMPP中, 一個服務器可以選擇性地連接到另一個服務器以激活域間或服務器間的通訊. 這種情形下, 兩個服務器需要在他們自身之間建立一個連接然后交換XML節; 這個過程所做的事情如下:
1. 確定要連接的IP地址和端口號, 典型的做法是對一個合格的域名做出解析(?[3.2](http://wiki.jabbercn.org/RFC6120#.E5.90.88.E6.A0.BC.E5.9F.9F.E5.90.8D.E7.9A.84.E8.A7.A3.E6.9E.90 "RFC6120")?)
1. 打開一個TCP連接
1. 打開一個XML流?[4.2](http://wiki.jabbercn.org/RFC6120#.E6.89.93.E5.BC.80.E4.B8.80.E4.B8.AA.E6.B5.81 "RFC6120")
1. 握手最好使用TLS來進行通道加密(?[5](http://wiki.jabbercn.org/RFC6120#STARTTLS.E6.8F.A1.E6.89.8B "RFC6120")?)
1. 使用簡單驗證和安全層?[SASL](http://wiki.jabbercn.org/RFC6120#SASL "RFC6120")?機制來驗證 (?[6](http://wiki.jabbercn.org/RFC6120#SASL.E6.8F.A1.E6.89.8B "RFC6120")?) *
1. 交換不限數量的XML節,可以服務器之間直接交換,也可以代表每臺服務器上的相關實體來交換,例如那些連到服務器上的客戶端 (?[8](http://wiki.jabbercn.org/RFC6120#XML.E8.8A.82 "RFC6120")?)
1. 關閉XML流 (?[4.4](http://wiki.jabbercn.org/RFC6120#.E5.85.B3.E9.97.AD.E4.B8.80.E4.B8.AA.E6.B5.81 "RFC6120")?)
1. 關閉TCP連接
- 互操作性提示: 在本文寫就的時候, 大多數已布署的服務器仍使用服務器回撥協議?[XEP?0220](http://wiki.jabbercn.org/RFC6120#XEP.E2.80.910220 "RFC6120")?來提供弱身份驗證,而不是使用SASL的 PKIX證書來提供強驗證, 特別在這些情況下,SASL握手無論如何將不會得到強驗證 (例如, 因為TLS握手沒有被對方服務器強制要求, 或因為當TLS握手時對方服務器提供的PKIX證書是自簽名的并且之前沒有被接受過); 細節請見?[XEP?0220](http://wiki.jabbercn.org/RFC6120#XEP.E2.80.910220 "RFC6120")?. 本文的解決方案顯然提供了一個更高級別的安全性 (參見?[13.6](http://wiki.jabbercn.org/RFC6120#.E9.AB.98.E5.AE.89.E5.85.A8.E6.80.A7 "RFC6120")?).
本文指定了客戶端如何連接到服務器以及基本的XML節語義. 然而, 本文不定義一個連接成功建立之后可能用來交換的XML節的"載荷"; 反之, 那些載荷被定義在各種XMPP擴展之中. 例如,?[XMPP?IM](http://wiki.jabbercn.org/RFC6120#XMPP.E2.80.91IM "RFC6120")?定義了基本的即時消息和出席信息功能的擴展. 另外, XSF創造了各種擴展協議,即XEP系列?[XEP?0001](http://wiki.jabbercn.org/RFC6120#XEP.E2.80.910001 "RFC6120")?,也為廣泛的應用程序定義了擴展.
### 術語
本文中的關鍵字 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", 和 "OPTIONAL" 的解釋參見[RFC 2119](http://tools.ietf.org/html/rfc2119 "http://tools.ietf.org/html/rfc2119")?[關鍵字](http://wiki.jabbercn.org/RFC6120#.E5.85.B3.E9.94.AE.E5.AD.97 "RFC6120")?.
特定的安全相關的術語的含義參見?[安全術語](http://wiki.jabbercn.org/RFC6120#.E5.AE.89.E5.85.A8.E6.9C.AF.E8.AF.AD "RFC6120")?; 這些術語包括但不限于, "assurance", "attack", "authentication", "authorization", "certificate", "certification authority", "certification path", "confidentiality", "credential", "downgrade", "encryption", "hash value", "identity", "integrity", "signature", "self-signed certificate", "sign", "spoof", "tamper", "trust", "trust anchor", "validate", and "verify".
特定的和證書,域名,應用服務身份相關的術語參見?[TLS?證書](http://wiki.jabbercn.org/RFC6120#TLS.E2.80.91.E8.AF.81.E4.B9.A6 "RFC6120")?; 這包括但不限于, "PKIX certificate", "source domain", "derived domain", 以及身份類型 "CN-ID", "DNS-ID", 和 "SRV-ID".
其他安全相關的術語定義于參考協議中 (例如, "denial of service" (拒絕服務)定義于?[DOS](http://wiki.jabbercn.org/RFC6120#DOS "RFC6120")?或 "end entity certificate" (終端實體證書)定義于?[PKIX](http://wiki.jabbercn.org/RFC6120#PKIX "RFC6120")?).
術語 "whitespace" (空格) 用于指代?[XML](http://wiki.jabbercn.org/RFC6120#XML "RFC6120")?中任何匹配"S"的字符或字符串, 也就是說, 一個或多個滿足?[ABNF](http://wiki.jabbercn.org/RFC6120#ABNF "RFC6120")?定義的SP, HTAB, CR, 或 LF 規則的實例.
術語 "localpart" (本地部分), "domainpart" (域部分), 以及 "resourcepart" (資源部分)定義于?[XMPP地址](http://wiki.jabbercn.org/RFC6120#XMPP.E5.9C.B0.E5.9D.80 "RFC6120")?.
術語 "bare JID" (純JID) 指代一個格式為 <localpart@domainpart> (對于一個位于某個服務器上的帳戶而言) 或 <domainpart> (對于一個服務器而言) 的XMPP地址.
術語 "full JID" (全JID) 指代一個格式為 <localpart@domainpart/resourcepart> (對一個典型的已授權客戶端或和某個帳號相關的設備而言) 或 <domainpart/resourcepart> (對于一個典型的資源或和某個服務器相關的文字)的XMPP地址.
術語 "XML stream" (也稱為 "stream" (流)) 定義于?[4.1](http://wiki.jabbercn.org/RFC6120#.E6.B5.81.E7.9A.84.E5.9F.BA.E6.9C.AC.E5.8E.9F.E7.90.86 "RFC6120")?.
術語 "XML stanza" (也稱為 "stanza" (節)) 定義于?[4.1](http://wiki.jabbercn.org/RFC6120#.E6.B5.81.E7.9A.84.E5.9F.BA.E6.9C.AC.E5.8E.9F.E7.90.86 "RFC6120")?. 有三種 stanzas(節): message, presence, 和 IQ ("Info/Query"的簡稱). 這些通訊原語分別定義于?[8.2.1](http://wiki.jabbercn.org/RFC6120#Message.E8.AF.AD.E4.B9.89 "RFC6120")?,?[8.2.2](http://wiki.jabbercn.org/RFC6120#Presence.E8.AF.AD.E4.B9.89 "RFC6120")?, 和?[8.2.3](http://wiki.jabbercn.org/RFC6120#IQ.E8.AF.AD.E4.B9.89 "RFC6120")?.
術語 "originating entity" (原實體)指的是第一次生成一個發送到XMPP網絡的stanza(節)的實體(例如, 一個已連接的客戶端, 一個附加的服務, 或一個服務器). 術語 "generated stanza" (生成的節)值的是生成的節那個節.
術語 "input stream" (輸入流)指定這樣一個XML流,服務器通過這個流從一個已連接的客戶端或遠端服務器接收數據, 而術語 "output stream" (輸出流)指定這樣一個流,服務器通過這個流發送數據到一個已連接的客戶端或遠程服務器. 以下術語指定一些動作,處理從輸入流收到的數據時服務器可以執行這些動作:
route(路由):
傳遞數據到一個遠端服務器讓它自行處理或最終遞送到一個和遠端服務器關聯的客戶端
deliver(遞送):
傳遞數據到一個已連接的客戶端
ignore(忽略):
丟棄數據不做任何處理或返回一個錯誤給發送者sender
當術語 "ignore" (忽略)用于客戶端處理收到的數據時, 短語 "without acting upon it" (不做任何處理)明確的包括不展示任何數據給使用者(人).
接下來的 "XML符號" 被?[IRI](http://wiki.jabbercn.org/RFC6120#IRI "RFC6120")?用于展示無法用僅用ASCII碼呈現的字符, 本文的一些例子使用了類似 "&#x...." 的格式來表現?[UNICODE](http://wiki.jabbercn.org/RFC6120#UNICODE "RFC6120")?字符串 (例如, 字符串 "?" 表示Unicode字符 LATIN SMALL LETTER R WITH CARON); 這種形式是絕對不會在XMPP系統將通過網絡發送的.
和?[URI](http://wiki.jabbercn.org/RFC6120#URI "RFC6120")?展現統一資源定位符的規則一樣, XMPP地址文本也是用 '<' 和 '>' 括起來的(盡管基本上它們不屬于 URIs).
例如, 被括起來的行是用來提高可讀性的, "[...]" 表示省略, 并且還是用了以下預定義字符串 (這些預定義的字符串不會通過網絡發送出去):
- C: = 客戶端
- E: = 任何XMPP實體
- I: = 發起實體
- P: = 對端服務器
- R: = 接收實體
- S: = 服務器
- S1: = 服務器1
- S2: = 服務器2
讀者需要注意這些例子不包括細節, 并且例子里的一些協議流程中, 展示的備用步驟不一定是由前一個步驟發送的確切的數據觸發的; 本文或常用參考文檔中的協議規范所用到的所有用例里面提供的例子都遵從上述規則. 所有例子都是虛構的并且交換的信息 (例如, 用戶名和密碼) 不代表任何現存的用戶和服務器.
### 體系結構
XMPP提供一種異步的端到端的結構化數據交換技術,在一個分布式的可全球尋址和出席信息感知的客戶端和服務器的網絡中使用直接的持久XML流。這種體系結構形式包含了普遍的網絡可用性的知識,以及在給定的客戶端-服務器和服務器-服務器會話的時候,不限數量的并發信息交易的概念,所以我們把它稱為 "并發交易可用性" ("Availability for Concurrent Transactions") (簡稱ACT) 來把它和來自WWW的 "Representational State Transfer"?[REST](http://wiki.jabbercn.org/RFC6120#REST "RFC6120")?體系結構形式區別開. 盡管XMPP的體系結構很大程度上類似于 email (參見?[EMAIL?ARCH](http://wiki.jabbercn.org/RFC6120#EMAIL.E2.80.91ARCH "RFC6120"), 它引入了一些變化以便于準實時通訊. ACT體系結構形式的獨特特性如下.
### 全局地址
和email一樣, 為了通過網絡路由和遞送消息,XMPP使用全球唯一地址(基于DNS). 所有XMPP實體可以在網絡上被尋址, 大部分客戶端和服務器以及很多外部服務可以被客戶端和服務器訪問. 通常, 服務器地址的格式為 <域部分> (例如, <im.example.com>), 屬于某臺服務器的帳號的格式為 <本地部分@域部分> (例如, <juliet@im.example.com>, 稱為 "純JID"), 而連接到一個特定的設備或資源并且已經被(服務器)授權可以和外部交互的客戶端的格式為 <本地部分@域部分/資源部分> (例如, <juliet@im.example.com/balcony>, 稱為 "全JID"). 因為歷史原因, XMPP地址常被稱為Jabber IDs 或 JIDs. 因為XMPP地址格式的正式規范依賴于國際化技術(本文撰寫時正在制定中),這個格式定義于?[XMPP?ADDR](http://wiki.jabbercn.org/RFC6120#XMPP.E2.80.91ADDR "RFC6120")?而非本文之中. 術語 "localpart"(本地部分), "domainpart"(域部分), 和 "resourcepart"(資源部分) 正式定義于?[XMPP?ADDR](http://wiki.jabbercn.org/RFC6120#XMPP.E2.80.91ADDR "RFC6120")?.
### 出席信息
XMPP讓一個實體能夠向其他實體聲明它的網絡可用性或者 "presence"(出席信息) . 在XMPP中, 這種可通訊狀態是用端到端的專用通訊元素來標識的: 即 <presence/> 節. 盡管網絡可用性對于XMPP消息交換并不是必需的, 它還是可以促進實時交互,因為消息發起者可以在發消息之前知道接收者在線并處于可通訊狀態. 端到端的出席信息定義于?[XMPP?IM](http://wiki.jabbercn.org/RFC6120#XMPP.E2.80.91IM "RFC6120")?.
### 持久流
每個點對點的一"跳"都建立了基于TCP長連接的持久XML流來保持可通訊狀態. 這些 "always-on" 客戶端-服務器 和 服務器-服務器 流使得任何時間每方都能夠推送數據到另一方并且立即路由和遞送. XML流定義于?[4](http://wiki.jabbercn.org/RFC6120#XML.E6.B5.81 "RFC6120")?.
### 結構化數據
XMPP中基本的協議數據單元不是一個XML流 (它只是為點對點通訊提供傳輸層) 而是一個 XML 節("stanza"), 它是一個通過流發送的XML片段. 一個節的根元素包括路由屬性 (類似 "from" 和 "to" 地址), 而節的子元素包含了遞送給目標接收者的載荷. XML節定義于?[8](http://wiki.jabbercn.org/RFC6120#XML.E8.8A.82 "RFC6120")?.
### 客戶端和服務器的分布式網絡
在實踐之中, XMPP是一個包含了很多互相通訊的客戶端和服務器的網絡(當然, 任何兩個給定的布署服務器之間的通訊都是嚴格謹慎的并且也和本地服務策略有關). 因此, 例如, 與服務器 <im.example.com> 關聯的用戶 <juliet@im.example.com> 能夠和服務器 <example.net> 關聯的用戶 <romeo@example.net> 交換消息,出席信息和其他結構化數據. 這個模式對使用全局地址的消息協議是很常見的, 例如email網絡 (見?[SMTP](http://wiki.jabbercn.org/RFC6120#SMTP "RFC6120")?和?[EMAIL?ARCH](http://wiki.jabbercn.org/RFC6120#EMAIL.E2.80.91ARCH "RFC6120")?. 結果, 在XMPP中端到端的通訊是邏輯上的點對點,而物理結構則是 客戶端-服務器-服務器-客戶端, 如下圖所示.
**圖1: 分布式客戶端-服務器 體系結構**
~~~
example.net <--------------> im.example.com
^ ^
| |
v v
romeo@example.net juliet@im.example.com
~~~