Jabber 協議 概述
Peter Saint-Andre
stpeter@jabber.org
1.4版Jabber服務協議的概述
1. 介紹
? Jabber是一個由開源社區發起并領導開發的即時消息和在線狀態的系統。Jabber系統和其它即時消息(IM)服務的一個功能上的差別在于Jabber擁有開放的XML協議。在保持Jabber1.0版本有關消息核心以及在線狀態的協議的基礎上,增加了一些必要的擴展。本文檔將對Jabber服務器1.4版的Jabber協議進行介紹。
? 在XML上下文的數據流中,Jabber開放的XML協議包括三個頂級XML元素:
l ? ? ? <message/>
l ? ? ? <presence/>
l ? ? ? <iq/>(info/query)
每一個元素通過屬性和名字空間包含大量的數據,這些屬性和名字空間都是Jabber的組成部分(但不包括為特殊應用的名字空間應用)。下面將描述整個Jabber協議。如果您想獲得關于Jabber系統結構的信息,請查看名為Jabber技術概述的文檔(http://docs.jabber.org/general/html/overview.html)。
2. XML流
? 一個Jabber會話由兩個平行的XML流組成,一個從客戶端到服務器端,另一個從服務端到客戶端。當一個Jabber客戶端連接上一個Jabber服務器時,這個客戶端將發起一個客戶端-服務器的XML流,同時作為響應,服務器也將發起一個服務器-客戶端的XML流。所有<message/>,<presence/>,以及<iq/>元素都被放在這些XML流的上下文中。下面就有一個例子:
? SEND:<?xml version=”1.0” encoding=”UTF-8” ?>
? SEND:<stream:stream
SEND:to=’jabber.org’
SEND:xmlns=’jabber:client’
SEND:xmlns:stream=’http://ether.jabber.org/streams’>
RECV:<stream:stream
RECV:xmlns:stream=’http://etherx.jabber.org/streams’
RECV:id=’39ABA7D2’
RECV:xmlns=’jabber:client’
RECV:from=’jabber.org’>
(XML for user session goes here)*
SEND:</stream:stream>
RECV:</stream:stream>
*注意:必須等到當一個<iq/>元素(特別指一個’jabber:iq:auth’名字空間下的<query/>元素)發送了認證信息后,服務器才會同意用戶會話進行工作。
3. <message/>元素
? <message/>元素是Jabber開放XML協議三個頂級元素中的一個。它被用來包含兩個Jabber用戶間互相發送消息內容,或者兩個Jabber IDs之間更一般的消息(因為,通過神奇的傳輸器,另一個IM系統可以用Jabber ID代替,如70902454@icq.jabber.org)。
3.1. 消息類型-“type”屬性
? Jabber支持幾種不同的消息,這些消息通過<message/>的“type”屬性來進行區分。下面就是“type”屬性的有效值:
3.1.1. [default](不設置“type”屬性)
? 表示本消息是一個普通消息。默認的情況下,客戶端在沒有設置屬性時,將消息類型定為普通消息。
? 例子:
<message to="romeo@montague.net/orchard">
<body>Wherefore art though Romeo?</body>
</message>
3.1.2.type=”chat”
? 表示消息需要被一個接一個的顯示在聊天界面上(一般是一條接一條的界面,不過實際界面可以被用戶自己定義。)
? 例子:
? <message to="romeo@montague.net/orchard" type="chat">
<body>Wherefore art though Romeo?</body>
</message>
3.1.3.type=”error”
? 表示消息被描述成一個錯誤條件。實際的錯誤在消息中用一個<error/>元素來描述。一個<message/>元素包括一個<body/>和一個<error/>。下面的例子將演示,當Juliet對一個不存在的用戶發送一個“hi”的消息時,將收到的包體:
? 例子:
<message
to="juliet@capulet.com"
from="flomeo@montague.net"
type="error">
<body>hi</body>
<error code="404">Not Found</error>
</message>
3.1.4. type=”groupchat”
? 表示本消息需要在一個聊天室的界面中進行顯示。
? 例子:
? <message to="cauldron@conference.witches.org" type="groupchat">
<body>Double, double toil and trouble</body>
</message>
3.2. <message/>其它屬性
? 除了設置“type”屬性,還可以通過下面的屬性修改<message/>元素:
3.2.1. “from”屬性
? 消息發送者的標志。總得來說,Jabber ID的”from”必須是user@host/resource的格式。從XML的觀點來說,這個屬性必須包含于所有的<message/>元素中,為了對付一些欺騙,實際應用中服務器添加或置換這個屬性。因此,它并不是客戶端開發者需要關心的問題。
? 例子:
? <message from="juliet@capulet.com/balcony">
<body>Wherefore art thou Romeo?</body>
</message>
3.2.2. “id”屬性
? “id”屬性是作為消息的一個唯一標志。它由Jabber客戶端或客戶庫(類似WinJab或JabberCOM),生成,客戶端用它來為跟蹤消息(比如將發送到一個群組聊天室的信息和從這個聊天室收到的消息相關聯,或將一個消息與它可能產生的錯誤相關聯)進行標識。“id”屬性是可選的,并且在系統的別的方是不可用的。
? 例子:
? <message to="romeo@montague.net/orchard" id="JCOM_85">
<body>Wherefore art thou Romeo?</body>
</message>
3.2.3. “to”屬性
? 表示消息的接收者。Jabber ID的“to”屬性一般是user@host/resource格式,user@host也可以被接受。如果接收者在線,通過user@host/resource方式解決,如果用戶不在線,直接發送離線存儲器。這個屬性是所有<message/>元素必須的。
? 例子:
<message to="romeo@montague.net/orchard">
<body>Wherefore art thou Romeo?</body>
</message>
3.3. <message/>中的子元素
? 下面的子元素是用來定義一個Jabber消息的上下文或數據元。
3.3.1. <body/>
? 這個元素包含消息的主要文本。<body/>元素只存在于一個<message/>元素中,并且只能包含明文。不過,它可以由其它子元素構成(如<error/>、<x/>)。
3.3.2. <error/>
? 當消息類型屬性被置為“error”時,這個元素將被使用。錯誤代碼被一個”type”屬性定義,這個”type”屬性包含代碼數,通過<error/>元素來包含一個這個錯誤的文本描述。<error/>元素必須包含在原始消息的<body/>中。下面的例子將演示,當Juliet向一個不存在的用戶發送“hi”消息后的包體:
? 例子:
<message
to="juliet@capulet.com"
from="flomeo@montague.net"
type="error">
<body>hi</body>
<error code="404">Not Found</error>
</message>
? 附文中有非法代碼與它們所定義的含義表。
3.3.3. <html/>
? <html/>元素結合XHTML名字空間(http://www.w3.org/1999/xhtml),為一個消息提供一個交替的名字空間,就像在email世界中規定同時發送普通文本與HTML版本的郵件消息一樣。這個功能使用的是W3C開發的基本XHTML格式(http://www.w3.org/TR/xhtml-basic/),關于Jabber在消息中的XHTML執行細節,請看Jabber消息的暫定格式規范(http://docs.jabber.org/draft-proto/html/xhtml.html)。所有XHTML的根元素都必須是<html xmlns=”http://www.w3.org/1999/xhmtl”></html>。這個根元素中,支持任何一個基本XHTML格式中定義的元素,但不是每一個元素可以通過即時消息的上下文來進行理解。
3.3.4. <subject/>
? 這是一個可選元素,包含消息的標題。
3.3.5. <thread/>
? 當一個Jabber客戶端發送一個”chat”類型的消息,將生成唯一的線程ID(通常是由發送者的Jabber ID和當前時間生成的一個hash)。消息發送者和接收者在聊天中后續的消息都包含一個<thread/>子元素,這個子元素包含原始線程ID。這使得消息發送者和接收者對回復進行認證并創建一個對話線程。下面的是例子:
<message
from="juliet@capulet.com/balcony"
to="romeo@montague.net/orchard"
type="chat">
<thread>AAC96FEFDE226C2C04BE8F2E19A2151B</thread>
<body>Art thou not Romeo and a Montague?</body>
</message>
<message
from="romeo@montague.net/orchard"
to="juliet@capulet.com/balcony"
type="chat">
<thread>AAC96FEFDE226C2C04BE8F2E19A2151B</thread>
<body>Neither, fair saint, if either thee dislike.</body>
</message>
3.3.6. <x/>
? <x/>元素作為一個擴展機制來使用,或發送從服務器發送命令給客戶端,或從一個客戶端發送命令到另一個客戶端。每次用到這個元素時,必須指明相關的XML名字空間。單一消息可以包含多個<x/>子元素實例。下列已定義的名字空間可以被<x/>子元素使用:
l ? ? ? jabber:x:autoupdate
l ? ? ? jabber:x:delay
l ? ? ? jabber:x:encrypted
l ? ? ? jabber:x:oob
l ? ? ? jabber:x:roster
這些名字空間在下面的Jabber名字空間中被更完整地描述。
下面是一個使用jabber:x:delay名字空間在加入的群組聊天室的顯示上下文的例子:
<message
type=’groupchat’
from=’cauldron@conference.witches.org’>
<body>Thrice the brinded cat hath mew’d.</body>
<x xmlns=’jabber:x:delay’
stamp=’10541031T21:43:40’>Cached In GC History</x>
</message>
4. <presence/>元素
? <presence/>元素提供關于一個Jabber實體的可用性信息。任何一個通過一個Jabber ID確認的實體可以與另一個實體進行在線狀態信息的通信,這種通信大多以訂閱在線狀態信息的方式進行。
? 所有實體表現出的在線狀態不是“可用”就是“不可用”。“可用”狀態表示發送者可以立即收到消息。“不可用”狀態表示發送者不能在當前時間收到任何數據。默認情況下,所有<presence/>元素除非包含type=”unavailable”屬性外,都表示“可用”。“可用”的更多特殊形勢通過<status/>和<show/>子元素進行指定。
4.1. “type”屬性
? <presence/>的“type”屬性根據不同目的使用。除了提示其它用戶本用戶的可用性狀態的“普通”用法外,還包括訂閱、取消訂閱、以及探測在線狀態信息。下面是“type”屬性的可用值:
4.1.1. type=”available”
? 如果沒有包含任何“type”屬性,在線狀態包將被設為type=”available”,用來提供用戶在線時的信息。一個type=”available”的在線狀態包通常包含一個<show/>元素以詳細說明Jabber實體的可用類型,以及一個<status/>元素,該元素包含人能看懂的關于該可用類型的描述。在線狀態包還可以包含一個<priority/>元素,來指明該連接的Jabber ID的優先級。
? 例子:
? <presence
from="juliet@capulet.com/balcony"
to="romeo@montague.net/orchard"/>
<show>away</show>
<status>Stay but a little, I will come again.</status>
</presence>
?
? <show/>元素的可用值為:
l ? ? ? away――Jabber用戶或實體在線,但不能馬上聯系上
l ? ? ? chat――Jabber用戶或實體在線并有興趣聊天
l ? ? ? dnd――Jabber用戶或實體在線,但不想被打擾(“dnd”表示“do not disturb”)
l ? ? ? xa――Jabber用戶或實體在線,但已經離開很長時間了(“xa”表示“extended away”)
<status/>可以包含任意特性數據,這些數據通常包含對于用戶狀態的描述,如,“開會中”是“away”的一個表現值,或者“忙于編碼”可以是“dnd”的一個表現。
4.1.2. type=”error”
? 當一個在線狀態包發送給一個不存在的JID時,或在發送在線狀態請求時發生一個錯誤時,服務器都將返回一個type=”error”的在線狀態包。
? 下面是一個例子(注意域名的類型):
<presence
? ? type="subscribe"
to="romeo@montague.nett"/>
? 回復的例子:
? <presence
? ? from="romeo@montague.nett"
to="juliet@capulet.com/balcony"
type="error">
<error code=’504’>Remote server timeout. Unable to deliver
packet.</error>
</presence>
4.1.3. type=”probe”
? 向一個特定實體(實體不能發送在線狀態消息給自己)發出在線狀態信息請求。服務器而非客戶端,進行一個探測請求。實際上,雖然Jabber客戶端也可以發送一個探測一個指定Jabber用戶是否在線的請求,但通常都是服務器端發出探測請求。注意,只有在發起請求的用戶在請求所對應的用戶的花名冊上,并且擁有“from”或“both”訂閱類型時,服務器才會發出探測請求。在下面的例子中,我們將看到我們的英雄Romeo向Juliet發出一個探測請求,Juliet所在服務器回復一個“狀態報告包”(包含jabber:x:delay名字空間中指明的上次在線狀態更新的時間戳)
? 探測請求的例子:
?
? <presence
from="romeo@montague.net"
to="juliet@capulet.com"
type="probe"/>
? 回復探測請求的例子:
? <presence
from="juliet@capulet.com/."
to="romeo@montague.net">
<status>Stay but a little, I will come again.</status>
<show>away</show>
? ? <x
xmlns="jabber:x:delay"
from="juliet@capulet.com/."
stamp="15310309T23:47:15"/>
</presence>
4.1.4. type=”subscribe”
? 發送一個請求,這個請求是接收者在其在線狀態改變時,自動發送在線狀態信息給發送者。
? 例子:
? <presence
from="romeo@montague.net"
to="juliet@capulet.com"
type="subscribe"/>
4.1.5. type=”subscribed”
? 發送一個消息,表明發送者接受了接受者對其再現狀態訂閱的請求。從現在起,當發送者的在線狀態信息改變時,服務器將會把狀態信息發送給接收者。
? 例子:
? <presence
from="juliet@capulet.com"
to="romeo@montague.net"
type="subscribed"/>
4.1.6. type=”unavailable”
? 例子:
? <presence
from="juliet@capulet.com"
to="romeo@montague.net"
type="unavailable">
<status>Disconnnected</status>
</presence>
4.1.7. type=”unsubscribe”
? 發送一個請求,表明接收者停止發送在線狀態信息給發送者。
? 例子:
?
<presence
from="juliet@capulet.com"
to="romeo@montague.net"
type="unsubscribe"/>
4.1.8. type=”unsubscribed”
? 這種類型的在線狀態包有兩個用途:
1. ? 發送一個表明發送者接受接收者關于不訂閱其在線狀態信息的請求的通知。服務器將不再發送發送者的在線狀態信息給接收者。
2. ? 拒絕一個訂閱請求。服務器將不再發送發送者的在線狀態信息給試圖訂閱其在線狀態信息的用戶。
例子:
<presence
from="romeo@montague.net"
to="juliet@capulet.com"
type="unsubscribed"/>
4.2. 其它<presence/>屬性
? 除了設置“type”屬性,還可以通過下列屬性修改<presence/>元素:
4.2.1. “from”屬性
標識在線狀態包的發送者。一般Jabber ID再“from”屬性中必須寫成user@host/resource的格式。從XML的觀點來說,這個屬性是所有<presence/>元素所必須的,而在實際應用中,都是服務器對該屬性進行添加和修改(防止一些欺騙的手段),因此客戶端開發者不需要考慮它。
例子:
<presence from="juliet@capulet.com/balcony"/>
4.2.2. “id”屬性
? 為在線狀態請求包配置唯一的驗證符。“id”屬性由Jabber客戶端或客戶庫(如Gabber或JabberCOM)生成,客戶端用其為在線狀態包的軌跡進行驗證。“id”屬性是可選的,并且不能用于系統其它任何地方。
? 例子:
? <presence to="romeo@montague.net/orchard" id="JCOM_86"/>
4.2.3. “to”屬性
? 標識在線狀態包的接收者。一般Jabber ID在“to”屬性中都是user@host/resource的格式,user@host的格式也是可以的,但當接收者在線時,它將轉化為user@host/resource。在Jabber的一般用法中,Jabber客戶端向服務器發出在線狀態包,服務器將這些在線狀態包發送到該用戶花名冊上所有的用戶。當一個Jabber客戶端發送的<presence/>元素中不含“to”屬性時,服務器將將其轉化為在線狀態包發送給指定的Jabber實體。下面的例子將演示這一過程。
? 發送給服務器的在線狀態的例子:
? <presence>
<status>Stay but a little, I will come again.</status>
<show>away</show>
</presence>
服務器發給指定用戶的在線狀態例子:
<presence
to="romeo@montague.net/orchard"
from="juliet@capulet.com/balcony">
<status>Stay but a little, I will come again.</status>
<show>away</show>
</presence>
4.3. <presence/>的子元素
? 下面的元素用于<presence/>協議。
4.3.1. <priority/>
? 在Jabber中,根據Jabber知道的設備數或位置數,一個用戶可以建立相同數量的連接。用戶可以給每一個資源賦予一個數字優先級(通過對指派給該資源的Jabber客戶端進行設置),這個優先級與<presence/>元素的子元素<priority/>方法進行通信。
? 當在線狀態包發送到服務器后,服務器有能力決定哪一個連接資源需要指派一個單一的Jabber ID,該資源將收到發往該Jabber ID的消息,這是因為數字最高的資源是默認或第一資源。如果最高優先級的資源不可用,消息和其它Jabber通信將發送給次高優先級的資源(當其它資源都不可用時,一個沒有從默認數到0的優先級的客戶端,也可以成為第一資源)
? 舉例來說,Julie可以通過兩個資源:the balcony 和 the chamber連接她的帳號juliet@capulet.com。如果“balcony”資源的優先級被設置為“2”,而“chamber”資源的優先級被設為“1”,而且兩個資源都可以連接,消息將發送到juliet@capulet.com/balcony,而不是juliet@capulet.com/chamber。
4.3.2. <show/>
? 可選的<show/>元素告訴Jabber客戶端如何顯示一個用戶的在線狀態。<show>標簽是一個典型的<status>標簽的伴隨標簽,<status>標簽包含更多在線狀態改變理由的描述信息。如果<show/>元素不在<presence/>元素中,Jabber接收客戶端將指明該用戶處于“普通”狀態。下面是四個可選項:
標簽
含義
<show>chat</show>
該客戶可以馬上聯系上
<show>away</show>
該客戶在線,但剛剛離開(如吃午飯,開會)
<show>xa</show>
該客戶在線,但已經處于非活動狀態很長時間了。
<show>dnd<show>
該用戶處于謝絕打擾的模式
4.3.3. <status/>
? <status/>元素包含更多關于用戶在線狀態的描述。大多數Jabber客戶端都包含一些<status/>元素的默認設置;另外,它們還允許我們提供富有個性的描述如“我在吃午飯”或者“釣魚中”。
4.3.4. <x/>
<x/>元素作為一個擴展機制來使用,或發送從服務器發送命令給客戶端,或從一個客戶端發送命令到另一個客戶端。每次用到這個元素時,必須指明相關的XML名字空間。單一消息可以包含多個<x/>子元素實例。下列已定義的名字空間可以被<x/>子元素使用:
l ? ? ? jabber:x:autoupdate
l ? ? ? jabber:x:delay
l ? ? ? jabber:x:encrypted
l ? ? ? jabber:x:oob
l ? ? ? jabber:x:roster
這些名字空間在下面的Jabber名字空間中被更完整地描述。
5. <iq/>元素
? 信息/查詢(IQ)在Jabber中在兩個實體間構建一個根本的會話,并且允許實體間來回傳送XML格式的請求和響應。信息/查詢主要的用處是取得或設置公共的用戶信息,比如名字,電子郵件,地址等等。但它的靈活設計使得任何種類的會話都可以發生。任何通過一個Jabber ID標識的實體都能通過一個IQ與其它實體進行會話。
5.1. “type”屬性
? <iq/>元素的“type”屬性用于決定信息/查詢是請求還是響應。下面是“type”屬性的可用值:
5.1.1. type=”error”
? 表示查詢失敗。實際錯誤在<iq/>元素的<error/>子元素中描述。
? 例子:
?
? <iq type="error" to="romeo@montague.net">
<error code="403">Forbidden</error>
</iq>
5.1.2. type=”get”
? 找回指派給一個查詢名字空間的信息。如果沒有設置屬性,默認情況,這個屬性包含在查詢中。一個type=”get”的<iq/>元素由一個子元素構成,這個子元素通常是<query>,但也可以是<vcard/>或另一個已有的子元素。不過,指定的子元素必須左空,以便接收一個用戶所需提供的信息的空間的清單。一個成功的get查詢的結果type=”result”的<iq/>元素,是元素嵌套在包含了所需信息的指定子元素(如<query>或<vcard/>)。
? 例子:
? <iq type="get">
<vCard xmlns="vcard-temp"/>
? </iq>
5.1.3. type=”result”
? 表示<iq/>包是一個type=”get”或type=”set”的<iq/>查詢的成功響應。這個成功查詢的結果是一個type=”result”的<iq/>元素,該元素嵌套在一個包含所查詢的信息的子元素中(如<query>、<vcard/>)。一個成功的查詢或獲取查詢結果的返回是一個空的type=”result”的<iq/>元素。一個不成功的返回是一個type=”error”的<iq/>元素。<iq type=”result”/>通常與“id”屬性的獲取、設定查詢有關。
例子:
? <iq type="result">
<vCard version="3.0" xmlns="vcard-temp">
vCard data goes here
</vCard>
</iq>
5.1.4. type=”set”
? 表示<iq/>包是對設值或更改現有數據值。一個type=”set”的<iq/>元素總是包含一個指定的子元素,通常是<query>,也可以是<vcard/>或者其它可以接受的子元素。一個設置命令查詢的成功返回是一個空的type=”result”的<iq/>元素。
? 例子:
? <iq type="set">
<vCard version="3.0">
vCard data goes here
</vCard>
</iq>
5.2. 其它<iq/>屬性
? 除了“type”屬性外,IQ元素還可以通過下面的屬性進行修改。
5.2.1. “from”屬性
? 表示iq包的發送者。從XML觀點來說,這個屬性是所有<iq/>元素所必須的,實際應用中這個屬性是服務器來增加和修改的(為防止某些欺騙),因此客戶端的開發人員不需要過多關注這個屬性。
? 例子:
?
? <iq from="romeo@montague.net"/>
5.2.2. “id”屬性
? 一個iq包只有唯一的標識。Jabber客戶端或客戶庫生成“id”屬性,客戶端通過它來標識<iq/>包,以完成對<iq/>包的跟蹤(如:一個type=”result”對應一個type=”get”或type=”set”)。“id”屬性是可選的,并且不能用于系統的其它地方。
? 例子:
? <iq type="get" from="juliet@capulet.com/balcony" id="JCOM_87"/>
<iq type="result" to="juliet@capulet.com/balcony" id="JCOM_87"/>
5.2.3 “to”屬性
? 表示iq包的接收者。在Jabber客戶端,對應“to”屬性的Jabber ID的格式為user@host/resource。user@host也是可以的,如果用戶在線,user@host將被置換成user@host/resource,如果用戶不在線,user@host將被直接指向一個離線模塊(對于類似服務器端網關這種非用戶實體,情況又有所不同,因為它們不擁有資源,并且只是簡單通過Jabber ID的一個“server”端口進行標識。Jud.jabber.org——Jabber用戶目錄就是這樣一個例子)。如果<iq/>包沒有<to>屬性,服務器將對該包進行處理。
? 例子:
? <iq to="juliet@capulet.com/balcony">
5.3 <iq/>的子元素
? 下面介紹<iq/>元素的子元素。
5.3.1. <error/>
? 當iq的屬性類型被設置為“error”時,將用到本屬性。錯誤代碼根據一個含有錯誤數的“type”屬性進行定義,<error/>員司包含該錯誤的文本描述。比如,下面就是一個壞請求:
?
? <error code="400">Bad Request</error>
?
? 在附錄中,列有錯誤編碼及其對應的錯誤描述。
5.3.2. <key/>
? <key/>元素為客戶端-服務器之間交互提供一層安全保護。它被用戶jabber:iq:register和jabber:iq:search名字空間中。
? 當一個客戶端發起一個與服務其之間的交互時,服務器將發送一個包含一個唯一值的<key>給客戶端。客戶端在返回<iq type=”set”/>的消息中,包含上訴唯一值到<key/>子元素中。這樣,服務器就認為該客戶端時接收到原來密碼的同一實體。
5.3.3. <query/>
? <iq/>元素中的<query/>子元素定義所執行的查詢的類型。特殊情況下,查詢可以擁有一個特殊的名字空間,這個名字空間是一個通過“xmlns”屬性定義的<query/>子元素。一個<iq/>元素中只能有一個<query/>子元素。
? 下面的例子是當我通過我的Linux機器上的Grabber客戶端登陸到服務器上,將出現的XML。
<iq type="set">
<query xmlns="jabber:iq:auth">
<username>stpeter</username>
<resource>Gabber</resource>
<digest>f1e881517e9917bb815fed112d81d32b4e4b3aed</digest>
</query>
</iq>
就象你看到的那樣,認證查詢通過客戶端認證名字空間(jabber:iq:auth)向服務器發送認證信息。一般,Jabber核心協議保留jabber:iq:*這樣的名字空間。而開發者可以通過增加jabber:iq:*名字空間對Jabber核心進行擴展。這些將在下面的名字空間中進行更完整的描述。
一個空<query/>子元素可以與<iq type=”get”>元素一起發送,這樣可以找回與<query/>子元素中指定的名字空間相關的一個Jabber實體的信息。比如,找回一個客戶端的花名冊(“聯系人名單”),下面的XML可以被發送:
<iq to="juliet@capulet.com/balcony" type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
6. 名字空間
? 現面是Jabber中的標準名字空間:
l ? ? ? jabber:iq:agent——代理工具
l ? ? ? jabber:iq:agents——有效的代理組
l ? ? ? jabber:iq:auth——簡單用戶認證
l ? ? ? jabber:iq:autoupdate——版本更新申請
l ? ? ? jabber:iq:browse——Jabber瀏覽
l ? ? ? jabber:iq:conference——一般會議
l ? ? ? jabber:iq:gateway——用戶地址網關
l ? ? ? jabber:iq:last——上次使用時間
l ? ? ? jabber:iq:oob——綁定數據輸出
l ? ? ? jabber:iq:private——私有數據存儲
l ? ? ? jabber:iq:register——注冊請求
l ? ? ? jabber:iq:roster——花名冊(聯系人名單)管理
l ? ? ? jabber:iq:search——用戶數據庫查詢
l ? ? ? jabber:iq:time——客戶端時間
l ? ? ? jabber:iq:version——客戶端版本
l ? ? ? jabber:x:autoupdate——版本通知申請
l ? ? ? jabber:x:conference——會議邀請
l ? ? ? jabber:x:delay——顯示的對象
l ? ? ? jabber:x:encrypted——加密的消息
l ? ? ? jabber:x:envelope——消息封套
l ? ? ? jabber:x:event——消息事件
l ? ? ? jabber:x:expire——消息終止
l ? ? ? jabber:x:oob——綁定數據(文件傳輸)輸出
l ? ? ? jabber:x:roster——內部的花名冊條目
l ? ? ? jabber:x:signed——標記的在線狀態
l ? ? ? vcard-temp——臨時的vCard
下面將詳細介紹這些名字空間的細節。
6.1. jabber:iq:agent——代理工具
? 代理工具名字空間包含一個代理的所有工具。jabber:iq:angents查詢通常用于注冊到一個指定的服務、代理、傳輸器。
? 它也可能檢驗一個指定代理的所有工具細節。比如,一個客戶端可以決定一個開放的注冊是否可以進行。
? 例子:
? <iq id="wjAgent" type="result" from="Jabber.org">
<query xmlns="jabber:iq:agent">
<agent jid="aim.jabber.org">
<name>AIM Transport</name>
<description>This is the AIM Transport</description>
<transport>AIM/AOL ScreenName</transport>
<service>aim</service>
<register/>
</agent>
</query>
</iq>
6.2. jabber:iq:angents——可用的代理列表
? 可用代理列表名字空間包含一組實體,這些實體擁有一些特殊工具,并能夠為另一個實體提供服務。大多數情況下,可用代理列表是用來顯示一臺服務器上的可用傳輸器列表。
? 注意:這個名字空間被jabber:iq:browse的支持者所反對(??)。
? 例子:
? <iq id="wjAgents" type="result" from="jabber.org">
<query xmlns="jabber:iq:agents">
<agent jid="users.jabber.org">
<name>User Directory</name>
<description>
You may register and create a public searchable
profile, and search for other registered Jabber
users.
</description>
<service>jud</service>
<register/>
<search/>
</agent>
<agent jid="aim.jabber.org">
<name>AIM Transport</name>
<description>This is the AIM Transport</description>
<transport>AIM/AOL ScreenName</transport>
<service>aim</service>
<register/>
</agent>
</query>
</iq>
6.3. jabber:iq:auth——簡單客戶端認證
簡單客戶認證名字空間是對客戶端進行認證的一個簡單機制,它為客戶端到服務器之間的連接創建一個資源。
認證成功返回一個type=”result”的IQ響應。不成功,就返回一個錯誤IQ元素。
如果沒有發送名字空間或密碼,如果服務器允許,服務器將創建一個匿名資源。
例子:
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<password>secret</password>
<resource>balcony</resource>
</query>
</iq>
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<digest>a5e052c48c455bf21d937ccf17225916d9486b09</digest>
<resource>balcony</resource>
</query>
</iq>
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<hash499>secret</hash499>
<resource>balcony</resource>
</query>
</iq>
6.4. jabber:iq:autoupdate——版本更新申請
? 版本更新申請名字空間允許客戶端對所有可用軟件更新進行申請請求。
? 例子:
<iq type="get" to="jabber.org" id="1">
<query xmlns="jabber:iq:autoupdate"/>
</iq>
6.5. jabber:iq:browse——Jabber瀏覽
? Jabber瀏覽名字空間的作用是,一是為Jabber世界中已有的Jabber IDs增加結構的一個途徑,一是發現為不同Jabber實體提供的服務或應用。一個Jabber瀏覽的基本概念就是一個jid-type(類似文件的一個模擬類型的概念)。下面是想象中的最高級別的jid-types,不過隨著時間的推移,一些其它的邏輯將被增加進來:
l ? ? ? 應用
l ? ? ? 會議
l ? ? ? 標題
l ? ? ? 關鍵字
l ? ? ? 回報
l ? ? ? 服務
l ? ? ? 用戶
上面每一個范疇都有一個子類列表,如用戶/客戶端,或用戶/設備(“客戶端”或“設備”只是一個“資源”的概念),會議/irc,服務/icq,標題/庫存。一般的,通過使用jabber:iq:browse名字空間你將擁有一個與上述某一jid-type范疇相對應的元素,這個元素通常有一個指定子類型的“type”屬性。
Jabber:iq:browse的一個用戶就是代替jabber:iq:agents名字空間來列出一個服務器上所對應的代理或其它服務。下面是一個瀏覽服務器的例子:
Jabber客戶端發送:
<iq type="get" to="jabber.org">
<query xmlns="jabber:iq:browse"/>
</iq>
Jabber服務器返回:
<iq type="result" from="jabber.org">
<service
type="jabber"
jid="jabber.org"
xmlns="jabber:iq:browse>
<service
type="jud"
jid="users.jabber.org"
name="Jabber User Directory">
<ns>jabber:iq:register</ns>
<ns>jabber:iq:search</ns>
</service>
<service
type="aim"
jid="aim.jabber.org"
name="AIM Transport">
<ns>jabber:iq:register</ns>
<ns>jabber:iq:search</ns>
</service>
<conference
type="private"
jid="conference.jabber.org"
name="Private Chatrooms">
</service>
</service>
</iq>
在會議中的一個例子:
<iq type="set" to="room@server">
<conference xmlns="jabber:iq:browse" name="Room Name">
<user jid="room@server/jidhash" name="nick1"/>
<user jid="room@server/jidhash" name="nick2"/>
</conference>
</iq>
6.6. jabber:iq:conference——一般會議
? 一般會議名字空間提供一個會議室的機制(如群組聊天室),并提供該會議室的入口。這個名字空間與</iq>元素配套使用來獲得一個會議室的信息,包括要求加入這個會議室的請求信息,以及為這個會議室設置信息(通常是為了加入這個房間)。一個普通進入房間的請求將和下面的類似:
1. ? 想要加入的房間提交一個type=”get”的請求。這個XML將是下面的形式:
<iq type="get" to="room@server">
<query xmlns="jabber:iq:conference"/>
</iq>
2. ? 接受來自要加入的房間的type=”result”的iq響應,其中有進入房間所需要的參數。這個XML將是下面的形式:
<iq type="result" from="room@server">
<query xmlns="jabber:iq:conference">
<nick/>
<secret/>
<privacy/>
<name>Room Name</name>
</query>
</iq>
這里所有的請求元素的子元素都是可選的。昵稱(nickname)元素表示進入房間需要一個昵稱。密鑰(secret)元素表示進入房間的用戶需要提供一個密碼。獨處(privacy)元素表示如果用戶在一個type=”set”(下面可以看到例子)的iq包中提供這樣的元素,會議服務器將隱藏用戶的真實Jabbere ID。名字(name)元素是房間的名字(用jabber:iq:browse瀏覽房間時可以看到同樣的房間名)。
3. ? 發送當前狀態給要加入的房間。XML如下:
<presence to="room@server"/>
4. ? 想要加入的房間提交一個type=”set”的iq包以及進入所需信息。XML如下:
<iq type="set" to="room@server">
<query xmlns="jabber:iq:conference">
<nick>mynick</nick>
<nick>mysecondnick</nick>
<secret>thesecret</secret>
</query>
</iq>
注意在用戶第一個選擇被接受時,用戶可以提交多個昵稱。如果用戶沒有提供昵稱,服務器將指派一個昵稱給用戶。
5. ? 收到你加入的房間的通知,這個iq以下面的格式返回:
<iq type="result" from="room@server">
<query xmlns="jabber:iq:conference">
<id>room@server/uniqueidnumber</id>
<nick>mynick</nick>
</query>
</iq>
這個唯一的ID號是用戶Jabber ID的一個哈希。
6.7. jabber:iq:gateway——用戶地址網關
? 一般通過一個網關或傳輸器(比如AIM傳輸器)來實現與非Jabber網絡用戶的通信,每一個非Jabber網絡都可能擁有唯一的用戶地址,這個地址可能和Jabber IDs并不統一。用戶地址網關就是解決這個問題的,它使得Jabber客戶端向非Jabber網絡用戶發出訂閱時給出正確Jabber IDs變得很容易。這些通過對用戶進行提示和會話,引導用戶提供創建一個正確Jabber ID所需信息來實現。下面將演示這種普通的交互:
1. ? 客戶端向網關發出帶有jabber:iq:gate名字空間查詢的iq get:
<iq type="get" to="aim.jabber.org">
<query xmlns="jabber:iq:gateway"/>
</iq>
2. ? 服務器返回一個包含請求批準及其描述文本的iq:
<iq type="result" from="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<desc>
Please enter the AOL Screen Name of the person
you would like to contact.
</desc>
<prompt>Screen Name</prompt>
</query>
</iq>
3. ? 客戶端向網關發送一個包含指定信息的iq set:
<iq type="set" to="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<prompt>Joe Cool</prompt>
</query>
</iq>
4. ? 服務器返回一個包含正確Jabber ID的iq result
<iq type="result" from="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<jid>JoeCool@aim.jabber.org</jid>
</query>
</iq>
6.8. jabber:iq:last——最后一次在線時間
最后一次在線時間名字空間提供一個標準的方法,通過這個方法可以查詢一個Jabber實體一個或多個服務更新時間,或者一個客戶最后一次連接(或活動)到一臺服務器上的時間。每一次返回的值都是一個秒的數目。進行查詢的實體可以通過下面的法則解釋獲取的信息:
l ? ? ? user@server/resource——用戶最后一次活動的時間
l ? ? ? user@server——用戶最后一次連接的時間
l ? ? ? server——服務器最后一次啟動的時間
例子(服務器):
<iq type="get" to="jabber.org">
<query xmlns="jabber:iq:last"/>
</iq>
<iq type="result" to="stpeter@jabber.org/Gabber" from="jabber.org">
<query xmlns="jabber:iq:last" seconds="124933"/>
</iq>
例子(客戶端):
<iq type="get" to="jer@jabber.org">
<query xmlns="jabber:iq:last"/>
</iq>
<iq type="result" to=stpeter@jabber.org/Gabber from="jer@jabber.org">
<query xmlns="jabber:iq:last" seconds="5024">
Disconnected
</query>
</iq>
6.9. jabber:iq:oob——綁定數據輸出
? 綁定數據輸出名字空間為客戶端-客戶端的文件傳輸提供一個標準方法,通過服務器的傳輸/代理的傳輸器實現一個特殊的名字空間:
例子:
<iq type="set" to="horatio@denmark.com" id="file_1">
<query xmlns="jabber:iq:oob">
<url>http://denmark.com/act4/letter-1.html</url>
<desc>There’s a letter for you sir.</desc>
</query>
</iq>
6.10. jabber:iq:private——私有數據存儲
? 私有數據存儲名字空間是Jabber服務器上存儲私有數據的一個機制。存儲的數據可以是任何合法的XML數據。在服務端存放客戶端的當前狀態信息是這個名字空間的典型用法。
? 例子1(客戶端存儲私有數據):
<iq type="set" id="1001">
<query xmlns="jabber:iq:private">
<winjab xmlns="winjab:prefs">
<defaultnick>Hamlet</defaultnick>
</winjab>
</query>
</iq>
例子2(客戶端找回私有數據):
<iq type="get" id="1002">
<query xmlns="jabber:iq:private">
<winjab xmlns="winjab:prefs"/>
</query>
</iq>
另外,對于私有數據存儲,1.4版服務器支持服務器上所有有效名字空間(以“jabber”開頭的名字空間保留,為Jabber系統進行調用)的XML數據。這個數據存在向服務器端發送type=”set”的iq包的用戶的花名冊中。
例子1(客戶端保存公有數據):
<iq type="set" id="1003">
<query xmlns="stpeter:public:favorites">
<fav_things>
<food>Thai</food>
<color>blue</color>
<composer>Bach</composer>
</fav_things>
</query>
</iq>
例子2(客戶端找回公有數據):
<iq type="get" id="1004">
<query xmlns="stpeter:public:favorites">
<fav_things/>
</query>
</iq>
6.11. jabber:iq:register——注冊請求
注冊請求名字空間對一個或多個服務進行注冊。它也被用來更新或刪除一個注冊。
例子:
<query xmlns="jabber:iq:register">
<instructions>
Some instructions to be displayed when the
user is filling out the form.
</instructions>
<username/>
<password/>
<email/>
<date/>
<key/>
</query>
6.12. jabber:iq:roster——聯系人名單管理
聯系人名單管理名字空間是客戶端用來管理他們的花名冊的,該花名冊保存在服務器上,這樣用戶可以在任何地方得到它。花名冊是該帳號上所有訂閱信息的命令列表,包括用戶昵稱和聯系列表。當用戶從任何一個資源登陸上來,服務器將把花名冊發送給用戶。
花名冊是一個條目的列表。每一個條目元素都有描述它的屬性。每一個條目元素都包含它所屬組的組元素。下面是描述<item/>元素的屬性:
l ? ? ? “jid”是條目的Jabber ID
l ? ? ? “subscription”所有和本條目相關的訂閱所對應的用戶的當前狀態。它可以是“none”(不可訂閱),“to”(有一個發到該條目的訂閱),“from”(從該條目發送一個訂閱給我們),“both”(to、from),或者“remove”(從花名冊上刪除一個條目)。
l ? ? ? “ask”是對這個條目的一個請求的當前狀態。Subscribe表示請求對該條目進行訂閱,它的值就是,Unsubscribe表示取消訂閱。
l ? ? ? “name”表示昵稱
通過使用一個<iq type=”set”/>,一個Jabber客戶端可以控制用戶的JabberID,名稱屬性,群組元素,并且可以在聯系人名單上創建或刪除聯系人。服務器根據客戶端對當前狀態訂閱請求的響應來管理其它所有屬性。
訂閱請求的例子:
<iq type="set" id="uniquevalue">
<query xmlns="jabber:iq:roster">
<item jid="romeo@montague.net"
name="Romeo"
subscription="none"
ask="subscribe">
<group>friends</group>
</item>
</query>
</iq>
當一個花名冊條目在服務器上改變時,服務器將把這個改變推送給一個用戶。這個推送是一個普通的從服務器發送到客戶端的<iq type=”set”/>包。下面是一個例子:
<iq type="set">
<query xmlns="jabber:iq:roster">
<item jid="romeo@montague.net" subscription="both"/>
</query>
</iq>
? 在上面的例子中,服務器推送給客戶端一個花名冊,表明該用戶對romeo@montague.net的當前狀態信息有訂閱。一個花名冊推送可能發生一個連接的任何時間中,該連接是另一個連接修改資源或服務器(修改訂閱屬性)的結果。客戶端只有使用花名冊推送來改變花名冊的顯示。但不是每次花名冊推送都對用戶起作用。
6.13. jabber:iq:search——用戶數據庫查詢
? 任何一個代理都可以成為一個查詢代理。例如,JUD查詢Jabber用戶,ICQ傳輸器查詢ICQ用戶。
? 用戶發送一個進行可查詢域的Get請求:
<iq
type="get"
id="1001"
to="users.jabber.org"
from="romeo@montague.net/orchard">
<query xmlns="jabber:iq:search"/>
</iq>
? 查詢代理返回一個可查域:
<iq type="result" id="1001" from="users.jabber.org">
<query xmlns="jabber:iq:search">
<instructions>Fill in a field to search for any
matching Jabber User
</instructions>
<name/>
<first/>
<last/>
<nick/>
<email/>
<key>067941fd96a6a2752a21abcb6d737130dd51dd50</key>
</query>
</iq>
? 注意這些域是以提示的形式返回。為了傳輸的安全還包含一個密鑰(下面會看到)。用戶現在可以在允許的域內進行標準的查詢了。用戶發回一個Set請求給代理進行實際查詢:
? <iq
type="set"
id="1002"
to="users.jabber.org"
from="romeo@montague.net/orchard">
<query xmlns="jabber:iq:search">
<last>Capulet</last>
<key>11b830e604215c3a2a24652c69fd4efa2a7a5746</key>
</query>
</iq>
? 服務器根據查詢返回結果:
<iq type="result" id="1002" from="users.jabber.org">
<query xmlns="jabber:iq:search">
<item jid="juliet@capulet.com">
<name>Juliet Capulet</name>
<first>Juliet</first>
<last>Capulet</last>
<nick>juliC</nick>
<email></email>
</item>
<item jid="sampson@capulet.com>
<name>Sampson Capulet</name>
<first>Sampson</first>
<last>Capulet</last>
<nick>sammy</nick>
<email></email>
</item>
</query>
</iq>
? 注意有兩套items標記含有指定信息。這是因為通過代理發送返回有兩種方法:
l ? ? ? 單一返回標簽
l ? ? ? 多個“pushed”到用戶的標簽,類似花名冊推送,如在一個時間上的一個記錄。
發送的返回的樣式是查詢代理的一個工具。比如:
<iq type="set" from="icq.jabber.org" id="1003">
<query xmlns="jabber:iq:search">
<item jid="7090245@icq.jabber.org">
<email>juliet@capulet.com</email>
<nick>juliC</nick>
<given>Juliet</given>
<family>Capulet</family>
</item>
</query>
</iq>
多個查詢結果通過服務器進行推送。當所有數據發送完畢,服務器將發送下面的返回結果:
<iq type="result" from="icq.jabber.org" id="1003">
<query xmlns="jabber:iq:search"/>
</iq>
客戶端接收到多個“sets”,每一個都被記錄,最后收到一個表示“數據結尾”的“返回”。在每一個<item>標簽中,JID屬性都被強制帶上。
例子:
<iq
type="get"
id="1001"
to="users.jabber.org"
from="juliet@capulet.com">
<query xmlns="jabber:iq:search"/>
</iq>
6.14. jabber:iq:time——客戶端時間
? 客戶端時間名字空間是客戶端改變當前時間的一個標準方法。
? 例子:
<iq type="result" from="stpeter@jabber.org">
<query xmlns="jabber:iq:time">
<utc>20010214T18:55:06</utc>
<display>2/15/00 4:55:06 PM</display>
</query>
</iq>
6.15. jabber:iq:version——客戶端版本
? 客戶端版本名字空間是得到另一個用戶的客戶端的版本信息的一個標準方法。
? 例子:
<iq type="result" from="stpeter@jabber.org/Gabber">
<query xmlns="jabber:iq:version">
<name>Gabber</name>
<version>0.8.1 (Powered by: jabberoo 1.0.0</version>
<os>Linux 2.2.16-22 i686</os>
</query>
</iq>
6.16. jabber:x:autoupdate——應用程序版本通知
? 版本更改申請名字空間使服務器可以在一個應用的新版本可用時通知客戶端。
? 例子:
?
<message from="winjab.sourceforge.net">
<x xmlns="jabber:x:autoupdate">A new version of WinJab
is available, see http://winjab.sourceforge.net/
</x>
</message>
6.17. jabber:x:conference——會議邀請
? 會議邀請名字空間使用戶可以邀請其它Jabber用戶到指定會議室。相關聯信息——該會議室的Jabber ID,內嵌在一個消息的<x/>元素中。
? 例子:
<message to="romeo@montague.net" from="juliet@capulet.com">
<body>Wherefore art thou Romeo?</body>
<x xmlns="jabber:x:conference" jid="balcony@conference.capulet.com/>
</message>
6.18. jabber:x:delay——標記對象延時
? 標記對象延時名字空間是消息和當前狀態信息的時間戳信息,其中,當一個Jabber實體不在線時,當前狀態信息可以保存并在稍后發送。當實體上線時,包含的信息標記對象延時名字空間使Jabber客戶端顯示出該包體最早產生的時間,而不是它發送給Jabber實體的時間。
? 例子:
<message
type=’groupchat’
from=’cauldron@conference.witches.org’>
<body>Thrice the brinded cat hath mew’d.</body>
<x xmlns=’jabber:x:delay’
stamp=’10541031T21:43:40’>Cached In GC History</x>
</message>
6.19. jabber:x:encrypted——加密消息
? 加密消息名字空間用來支持使用公共密鑰(一般通過客戶端使用PGP或GPG,服務端用同樣的名字空間進行加密來實現)加密的消息交互。一個相關的名字空間,jabber:x:signed,用來進行當前狀態信息的加密。
? 例子:
<message from=’juliet@capulet.com/balcony’ to=’romeo@montague.net/orchard’>
<body>This Message is Encrypted</body>
<x xmlns=’jabber:x:encrypted’>
hQEOA7ucqu53AhlPEAP/ZbU6oPnRAbIcUxMK1XRVnkgZ/Agtq1tcTQuEZxbpZLl4
C/4psQGLgBU5h5Y3/khxtJTPXKn1izyc+DRZ8hqn2p4mwC8ioKTBJ6P6dfEpQEyt
a4bimM5fqdeh4gRkMhwThRSJxBCJBVVWFEViu+0KlHHB5AeeL4qwRGb2dhGjIgQD
/R9x0D0qtgBGwf/TVnRGZYRX7epxCNuNDEYKZSs4LEoTPL8CVsAWOzS2QgS0GBqt
tFDKId6XaNu36dB2D8VHdxQnI8RtHo9pfTYDaXWB3dMGTt896iEO/sTuucYObf3s
K5Kygg0uWpBpvQPj8Y041FhnUBz8DRGCnuFLQxCI6ch4ybauXfOKNOGDQwmsnJZm
6OaeVFUwdsedI3c6VdQtodnWVutckR5BOjnn0VqnhrVTu7cp6VXrrRK4g9atPEe6
C4R/MilBjzIJBcET0jhWuAyiBo3gN/6IqYRZNSXL9ZqGPJwNTlYim1EHN3qBqiUw
zUMamEoRzcusn80Z7kylve5ujIeSD/pVwoawHHvLp92kO2hd0yGD0UrWSfKU1o6y
EY8yhZ5P1v02pIKigAUI2c6LTDxt/KhSxQ==
=fijN
</x>
</message>
6.20. jabber:x:envelope——消息信封
? 消息信封名字空間是表明消息有更多的尋址方式,如聯合email進行的尋址。下面是一些所支持的名字空間:
l ? ? ? to
l ? ? ? cc
l ? ? ? replyto
l ? ? ? from
l ? ? ? forwardedby
上述每一個元素都帶有一個”jid”屬性來標識Jabber實體是發送、中轉、還是收到消息。
例子:
<message from=’juliet@capulet.com/tomb’ to=’romeo@montague.net/tomb’>
<body>And there I am. Where is my Romeo?</body>
<x xmlns=’jabber:x:envelope’>
<to jid=’romeo@heaven.org>Romeo</to>
<forwardedby jid=’root@heaven.org>God</forwardedby>
</x>
</message>
6.21. jabber:x:event——消息事件
? 消息時間名字空間是標識一條消息的狀態的一個機制。現在,事件與一條消息如下般相關聯:
l ? ? ? <composing/>——個用戶正在對消息進行回復
l ? ? ? <delivered/>——發送給指定接收者的消息
l ? ? ? <displayed/>——顯示給指定接收者的消息
l ? ? ? <offline/>——為離線進行存儲的消息
對于客戶端來說,這些消息事件的支持是可選的,而且,只有在另一用戶在聊天中發出請求,這些消息事件才會被發送。不同的Jabber客戶端將對當前狀態消息事件進行不同的顯示。
對消息通知的請求的例子:
<message
from="juliet@capulet.com/balcony"
to="romeo@montague.net/orchard"
id="1001">
<body>By whose direction found’st thou out this place?</body>
<x xmlns="jabber:x:event">
<composing/>
</x>
</message>
發送消息通知的例子:
<message from="romeo@montague.net/orchard" to="juliet@capulet.com/balcony">
<body>By whose direction found’st thou out this place?</body>
<x xmlns="jabber:x:event">
<composing/>
<id>1001<id/>
</x>
</message>
? 可以同時請求多個消息事件。
6.22. jabber:x:expire——消息到期
? 消息到期名字空間是說明一條消息擁有一個有限的存活事件的一個簡單擴展。如果消息被離線存儲,而到了到期時間,服務器將不再發送該消息。如果一條消息為預覽就進行發送,Jabber客戶端可以選擇不顯示該消息。“secondes”屬性定義消息發送的事件。
? 例子:
<message from="sailor@denmark.com" to="horatio@denmark.com">
<body>There’s a letter for you sir</body>
<x xmlns="jabber:x:expire" seconds="3600"/>
</message>
6.23. jabber:x:oob——綁定數據輸出
? 綁定數據輸出名字空間使用戶可以通過交換一個標準的URL來實現文件傳輸的目電。使用jabber:x:oob的URLs交換可以包含任一消息(在一個<x/>子元素內),感覺就像email里的附件一樣。多個附件可以包含在同一個消息中。
? 例子:
<message from="sailor@denmark.com" to="horatio@denmark.com">
<body>URL Attached.</body>
<x xmlns="jabber:x:oob">
<url>http://denmark.com/act4/letter-1.html</url>
<desc>There’s a letter for you sir</desc>
</x>
</message>
6.24. jabber:x:roster——內置的花名冊條目
? 內置的花名冊條目使用戶可以在一個消息中包含花名冊條目,這樣很容易在用戶之間發送聯系方式。每一個花名冊條目都包含在一個<x/>的一個<item/>子元素中。這個<x/>元素一般用在一個<message/>元素中,但這不是必須的。
? 例子:
<message to="hamlet@denmark.com">
<body>
Here are some new Jabber users
to add to your contact list!
</body>
<x xmlns="jabber:x:roster">
<item jid="claudius@denmark.com" name="King">
<group>Royalty</group>
</item>
<item jid="horatio@denmark.com" name="Horatio">
<group>Friends</group>
</item>
<item jid="fortinbras@norway" name="Prince Fortinbras"/>
</x>
</message>
6.25. jabber:x:signed——有符號的當前狀態
? 有符號的當前狀態名字空間用來支持交換使用公共密鑰(客戶端使用PGP或GPG,服務端使用同樣的名字空間進行加密)加密的當前狀態信息。一個相關的名字空間,jabber:x:encrypted用來支持加密消息。
? 例子:
<presence from=’juliet@capulet.com/balcony’ to=’romeo@montague.net/orchard’>
<show>away</show>
<status>be back later</status>
<x xmlns=’jabber:x:signed’>
iD8DBQA6kasv0xpc2/POfPkRAnz0AJ9UEYYWWSReddIKk3AYMfTFtqQDJwCfbcLd
JcSUOR0FlS+rDFjAPaSMgSM+iNaNm
</x>
</presence>
6.26. vcard-temp——臨時vCard
? vCard格式是一個“電子商務卡的標準格式,通過使用通過互聯網進行個人數據的直接交換,如同在非互聯網下的環境一樣”。由于XML的vCard的格式還沒有標準化,Jabber.org項目在XML的vCard標準建立之前,暫時設置了這樣一個臨時名字文件。由于這幾年在vCard的XML的官方標準的指定上沒有任何進步,Jabber.org開發者專門為這個項目創建了一個項目吸引Jabber社區外其它開發者的注意。因此,最后的XML的vCard格式的最后DTD可能會在下面的URL中找到:
http://www.vcard-xml.org/
?
? 例子1(對vCard的客戶端請求):
<iq type="get">
<vCard xmlns="vcard-temp"/>
</iq>
? 例子2(客戶端收到vCard數據):
<iq type="result">
<vCard version="3.0" xmlns="vcard-temp">
vCard data goes here
</vCard>
</iq>
? 例子3(客戶端向服務端發送vCard):
<iq type="set">
<vCard version="3.0">
vCard data goes here
</vCard>
</iq>
7. 使用用例
? 這一部分提供一些在Jabber協議上略有不同的觀點,通過用例來闡述。下面每一個例子都展示一個Jabber用戶完成一個完整的任務的消息流程,該流程包括接收和發送,如注冊到一臺服務器,登陸,改變當前狀態,或者發送一條消息。如果時間允許,我將把這部分引申的更遠。
7.1. Jabber用戶注冊
? 本用例同時邪顯示Jabber用戶向服務器開啟一個socket的連接,以及服務器的響應(如:<stream:stream>標簽)。
1. ? Jabber用戶通過開啟一個從客戶端到服務器端的XML流,來申請一個在服務器上的socket連接。
SEND: <stream:stream
to=’capulet.com’
xmlns=’jabber:client’
xmlns:stream=’http://etherx.jabber.org/streams’>
2. ? 服務器通過開啟一個從服務器到客戶端的XML流進行回復。
RECV: <stream:stream
from=’capulet.com’
id=’180763465’
xmlns=’jabber:client’
xmlns:stream=’http://etherx.jabber.org/streams’>
3. ? Jabber用戶提供一個需要注冊一個帳號(理論上,這需要一個不同的順序:首先詢問服務器需要什么信息,然后服務器器告知客戶端需要什么樣的信息;但在實際中,假定需要的信息是:用戶名,資源,密碼)的信息。
SEND: ? <iq id=’1’ type=’set’>
? ? ? <query xmlns=’jabber:iq:register’>
? ? ? ? ? <username>Juliet</username>
? ? ? ? ? <resource>balcony</resource>
? ? ? </query>
? ? </iq>
4. ? 服務器響應一個空的類型為”result”的iq元素,表示注冊已成功。
RECV: ? <iq id=’1’ type=’result’/>
7.2. Jabber用戶登陸
1. ? Jabber用戶詢問服務器,登陸所需要提供的信息。
SEND: <iq id=’2’ type=’get’>
? ? ? <query xmlns=’jabber:iq:auth’>
? ? ? ? <username>Juliet</username>
? ? ? </query>
? ? </iq>
2. ? 服務器提示Jabber用戶登陸所需要的信息。
RECV: <iq id=’2’ type=’result’>
? ? ? <query xmlns=’jabber:iq:auth’>
? ? ? ? <username>Juliet</username>
? ? ? ? <password/>
? ? ? ? <digest/>
? ? ? ? <sequence>500<sequence/>
? ? ? ? <token>3B905BFD</token>
? ? ? ? <resource/>
? ? ? </query>
? ? </iq>
3. ? Jabber用戶提供所需的信息——在本例中,是一個<hash/>元素,它是對信息進行一個零度知識認證的一個哈希。(詳情請見http://docs.jabber.org/draft-proto/html/zerok.html)。
SEND: <iq id=’3’ type=’set’>
? ? ? <query xmlns=’jabber:iq:auth’>
? ? ? ? <username>Juliet</username>
? ? ? ? <resource>balcony</resource>
? ? ? ? ? ? ? ? <hash>77d7eacde5e56b9622d0a075cb88361b110f
b9d7</hash>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
4. ? 服務器響應一個空的類型為”result”的iq元素,表明登陸成功。
RECV: <iq id=’3’ type=’result’/>
5. ? Jabber用戶發送當前狀態給服務器,表明其在線。
SEND: <presence>
? ? ? <status>Online</status>
? ? </presence>
7.3. Jabber用戶增加一個聯系人
1. ? Jabber客戶端在花名冊上增加一個聯系人(只是預備的操作)。
SEND: <iq type=’set’>
? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? <item jid=’romeo@montague.net’
Name=’remeo’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
2. ? Jabber用戶發送一個對該聯系人的訂閱請求。
SEND: <presence to’remeo@montague.net’ type=’subscribe’>
? ? ? <status>Wherefore are thou?</status>
? ? </presence>
3. ? 服務器發送一個花名單推送給用戶一個新條目和一個類型為”none”的訂閱(早已有了該訂閱)。
RECV: <iq type=’set’>
? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? <item jid=’romeo@montague.net’
name=’romeo’
subscription=’none’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
4. ? 服務器發送一個類型為”result”的iq包,表示花名冊推送成功(讓人有點疑惑的是,這個包是從Jabber用戶發送到Jabber用戶的!)
RECV: <iq
from=’juliet@capulet.com/balcony’
to=’julie@capulet.com/balcony’
type=’result’>
5. ? 服務器發送另一個花名單推送,這次是ask=’subscribe’屬性,表示訂閱的狀態未定。
RECV: <iq type=’set’>
? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? <item
ask=’subscribe’
jid=’romeo@montague.net’
name=’romeo’
subscription=’none’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
6. ? Romeo對訂閱請求的下一個響應會是什么呢?現在我們假定訂閱以Romeo接受訂閱請求為“結束”的。
RECV: <presence
from=’romeo@montague.net’
to=’juliet@capulet.com’
type=’subscribed’/>
7. ? 服務器再次發送一個花名單推送給客戶端,這次subscription=’to’,表示訂閱請求被接受了(Juliet現在可以訂閱到Romeo的當前狀態了)。
RECV: <iq type=’set’>
? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? <item
jid=’romeo@montague.net’
name=’romeo’
subscription=’to’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
7.4. Jabber用戶獲得花名冊
? ? ? SEND: <iq type=’get’>
? ? ? ? ? ? ? <query xmlns=’jabber:iq:roster’/>
? ? ? ? ? ? </iq>
RECV:<iq from=’juliet@capulet.com/balcony’ type=’result’> ?
? ? ? ? ? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? ? ? ? ? <item
jid=’romeo@montague.net’
name=’romeo’
subscription=’both’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
7.5. Jabber用戶發送一條消息
? ? ? SEND: <message to’romeo@montague.net’>
? ? ? ? ? ? ? <body>Wherefore are thou?</body>
? ? ? ? ? ? </message>
? 注意:服務器會根據Jabber用戶的會話信息加上一個源地址,這樣接收者收到消息時,消息中已經包含了源地址。
7.6. Jabber用戶改變當前狀態
? ? SEND: <presence>
? ? ? ? ? ? <status>stepped away…</status>
? ? ? ? ? ? <show>away</show>
? ? ? ? </presence>
7.7. Jabber用戶登出
? 登出時很容易的,只需要關閉<stream>……
? ? SEND: </stream:stream>
? ? RECV: </stream:stream>
8. 參考文獻
? 本協議參考以下文獻
l ? ? ? Jabber開發指南(http://docs.jabber.org/jpg/)
l ? ? ? Jabber協議――標準(http://docs.jabber.org/proto/)
l ? ? ? Jabber協議――草案(http://docs.jabber.org/draft-proto/)
l ? ? ? Romeo and Juliet
(http://tech-two.mit.edu/Shakespeare/Tragedy/romoandjuliet/full.html)
9. 結束語
? 本文檔提供了一個關于Jabber的XML協議的一個詳細的怪數。如果你對本文檔有任何問題,請通過email或Jabber的方式自由地與作者聯系(Peter Saint-Andre),他的帳號時stpeter@jabber.org。
10. 版權信息
This document is copyright 2001 by Peter Saint-Andre.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (http://www.gnu.org/copyleft/fdl.html),
Version 1.1 or any later version published by the Free Software Foundation, with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You may obtain a
copy of the GNU Free Documentation License from the Free Software Foundation by
visiting http://www.fsf.org/ or by writing to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA
附錄 A 標準錯誤代碼
? 下面是Jabber中錯誤代碼的一些簡要描述。Jabber服務器在碰到不同的錯誤條件下生成這些錯誤代碼。一般Jabber錯誤代碼以HTTP規格的RFC 2616(http://www.ietf.org/rfc/rfc2616.txt)為基礎。但Jabber沒有使用所有的HTTP的錯誤代碼,并且Jabber錯誤代碼與HTTP錯誤代碼相對應時,通常只有Jabber自己的含義。注意本附錄只包含Jabber服務器生成的錯誤代碼,而不包括服務器端組件如網關發到外部消息系統。
錯誤代碼
描述
注意
302
重定向
盡管HTTP規定中包含八種不同代碼來表示重定向,Jabber只用了其中一個(用來代替所有的重定向錯誤)。不過Jabber代碼302是為以后的功能預留的,目前還沒有用到
400
壞請求
Jabber代碼400用來通知Jabber客戶端,一個請求因為其糟糕的語法不能被識別。例如,當一個Jabber客戶端發送一個的訂閱請求給它自己活發送一條沒有包含“to”屬性的消息,Jabber代碼400就會產生。
401
未授權的
Jabber代碼401用來通知Jabber客戶端它們提供的是錯誤的認證信息,如,在登陸一個Jabber服務器時使用一個錯誤的密碼,或未知的用戶名。
402
所需的費用
Jabber代碼402為未來使用進行保留,目前還不用到。
403
禁止
Jabber代碼403被Jabber服務器用來通知Jabber客戶端該客戶端的請求可以識別,但服務器拒絕執行。目前只用在注冊過程中的密碼存儲失敗。
404
沒有找到
Jabber代碼404用來表明Jabber服務器找不到任何與JabberID匹配的內容,該JabberID是一個Jabber客戶端發送消息的目的地。如,一個用戶打算向一個不存在的JabberID發送一條消息。如果接受者的Jabber服務器無法到達,將發送一個來自500級數的錯誤代碼。
405
不允許的
Jabber代碼405用在不允許操作被’from’地址標識的JabberID。例如,它可能產生在,一個非管理員用戶試圖在服務器上發送一條管理員級別的消息,或者一個用戶試圖發送一臺Jabber服務器的時間或版本,或者發送一個不同的JabberID的vCard。
406
不被接受的
Jabber代碼406用于服務器因為某些理由不接受一個包。例如,這個可能發生在,一個Jabber客戶端試圖使用jabber:iq:private在服務器上存儲信息,但當前的用于存儲的名字空間用”jabber:”開頭(在Jabber里是一個被存的XML開頭)。另一種可能產生406錯誤的情況是當一個Jabber客戶端試圖用一個空密碼注冊到一臺Jabber服務器上。
407
必須注冊
Jabber代碼407當前不被使用
408
注冊超時
當一個Jabber客戶端不能在服務器準備好的時間內發起一個請求時,Jabber服務器生成Jabber代碼408。這個代碼當前只用于Jabber會話管理器使用的零度認證模式中。
409
沖突
略
500
服務器內部錯誤
當一臺Jabber服務器遇到一種預期外的條件,該條件阻止服務器處理來自Jabber客戶端的包,這是將用到Jabber代碼500。現在,唯一會引發500錯誤代碼的時間是當一個Jabber客戶端試圖通過服務器認證,而該認證因為某些原因沒有被處理(如無法保存密碼)。
501
不可執行
當服務器不支持Jabber客戶端請求的功能,使用Jabber代碼501。例如,該代碼只當Jabber客戶端發送一個認證請求,而該認證請求不包含服務器配置中定義的任何一種認證方式時,服務器發送Jabber代碼501。這個代碼還被用于,當一個Jabber客戶端試圖注冊一個不允許注冊的服務器。
502
遠程服務器錯誤
當因為無法到達遠程服務器導致轉發一個包失敗時,使用Jabber代碼502。該代碼發送的特殊例子包括一個遠程服務器的連接的失敗,無法獲取遠程服務器的主機名,以及遠程服務器錯誤導致的外部時間過期。
503
服務無法獲得
當一個Jabber客戶端請求一個服務,而Jabber服務器通常由于一些臨時原因無法提供該服務時,使用Jabber代碼503。例如,一個Jabber客戶端試圖發送一條消息給另一個用戶,該用戶不在線,但它的服務器不提供離線存儲服務,服務器將返回一個503錯誤代碼給發送消息的JabberID。當為vcard-temp和jabber:iq:private名字空間設置信息時,出現通過xdb進行數據存儲的寫入錯誤,也使用該代碼。
504
遠程服務器超時
Jabber代碼504用于下列情況:試圖連接一臺服務器發生超時,錯誤的服務器名。
510
連接失敗
Jabber代碼510目前還沒有使用。
源文:http://www.blogjava.net/codefans/articles/20022.html
Peter Saint-Andre
stpeter@jabber.org
1.4版Jabber服務協議的概述
1. 介紹
? Jabber是一個由開源社區發起并領導開發的即時消息和在線狀態的系統。Jabber系統和其它即時消息(IM)服務的一個功能上的差別在于Jabber擁有開放的XML協議。在保持Jabber1.0版本有關消息核心以及在線狀態的協議的基礎上,增加了一些必要的擴展。本文檔將對Jabber服務器1.4版的Jabber協議進行介紹。
? 在XML上下文的數據流中,Jabber開放的XML協議包括三個頂級XML元素:
l ? ? ? <message/>
l ? ? ? <presence/>
l ? ? ? <iq/>(info/query)
每一個元素通過屬性和名字空間包含大量的數據,這些屬性和名字空間都是Jabber的組成部分(但不包括為特殊應用的名字空間應用)。下面將描述整個Jabber協議。如果您想獲得關于Jabber系統結構的信息,請查看名為Jabber技術概述的文檔(http://docs.jabber.org/general/html/overview.html)。
2. XML流
? 一個Jabber會話由兩個平行的XML流組成,一個從客戶端到服務器端,另一個從服務端到客戶端。當一個Jabber客戶端連接上一個Jabber服務器時,這個客戶端將發起一個客戶端-服務器的XML流,同時作為響應,服務器也將發起一個服務器-客戶端的XML流。所有<message/>,<presence/>,以及<iq/>元素都被放在這些XML流的上下文中。下面就有一個例子:
? SEND:<?xml version=”1.0” encoding=”UTF-8” ?>
? SEND:<stream:stream
SEND:to=’jabber.org’
SEND:xmlns=’jabber:client’
SEND:xmlns:stream=’http://ether.jabber.org/streams’>
RECV:<stream:stream
RECV:xmlns:stream=’http://etherx.jabber.org/streams’
RECV:id=’39ABA7D2’
RECV:xmlns=’jabber:client’
RECV:from=’jabber.org’>
(XML for user session goes here)*
SEND:</stream:stream>
RECV:</stream:stream>
*注意:必須等到當一個<iq/>元素(特別指一個’jabber:iq:auth’名字空間下的<query/>元素)發送了認證信息后,服務器才會同意用戶會話進行工作。
3. <message/>元素
? <message/>元素是Jabber開放XML協議三個頂級元素中的一個。它被用來包含兩個Jabber用戶間互相發送消息內容,或者兩個Jabber IDs之間更一般的消息(因為,通過神奇的傳輸器,另一個IM系統可以用Jabber ID代替,如70902454@icq.jabber.org)。
3.1. 消息類型-“type”屬性
? Jabber支持幾種不同的消息,這些消息通過<message/>的“type”屬性來進行區分。下面就是“type”屬性的有效值:
3.1.1. [default](不設置“type”屬性)
? 表示本消息是一個普通消息。默認的情況下,客戶端在沒有設置屬性時,將消息類型定為普通消息。
? 例子:
<message to="romeo@montague.net/orchard">
<body>Wherefore art though Romeo?</body>
</message>
3.1.2.type=”chat”
? 表示消息需要被一個接一個的顯示在聊天界面上(一般是一條接一條的界面,不過實際界面可以被用戶自己定義。)
? 例子:
? <message to="romeo@montague.net/orchard" type="chat">
<body>Wherefore art though Romeo?</body>
</message>
3.1.3.type=”error”
? 表示消息被描述成一個錯誤條件。實際的錯誤在消息中用一個<error/>元素來描述。一個<message/>元素包括一個<body/>和一個<error/>。下面的例子將演示,當Juliet對一個不存在的用戶發送一個“hi”的消息時,將收到的包體:
? 例子:
<message
to="juliet@capulet.com"
from="flomeo@montague.net"
type="error">
<body>hi</body>
<error code="404">Not Found</error>
</message>
3.1.4. type=”groupchat”
? 表示本消息需要在一個聊天室的界面中進行顯示。
? 例子:
? <message to="cauldron@conference.witches.org" type="groupchat">
<body>Double, double toil and trouble</body>
</message>
3.2. <message/>其它屬性
? 除了設置“type”屬性,還可以通過下面的屬性修改<message/>元素:
3.2.1. “from”屬性
? 消息發送者的標志。總得來說,Jabber ID的”from”必須是user@host/resource的格式。從XML的觀點來說,這個屬性必須包含于所有的<message/>元素中,為了對付一些欺騙,實際應用中服務器添加或置換這個屬性。因此,它并不是客戶端開發者需要關心的問題。
? 例子:
? <message from="juliet@capulet.com/balcony">
<body>Wherefore art thou Romeo?</body>
</message>
3.2.2. “id”屬性
? “id”屬性是作為消息的一個唯一標志。它由Jabber客戶端或客戶庫(類似WinJab或JabberCOM),生成,客戶端用它來為跟蹤消息(比如將發送到一個群組聊天室的信息和從這個聊天室收到的消息相關聯,或將一個消息與它可能產生的錯誤相關聯)進行標識。“id”屬性是可選的,并且在系統的別的方是不可用的。
? 例子:
? <message to="romeo@montague.net/orchard" id="JCOM_85">
<body>Wherefore art thou Romeo?</body>
</message>
3.2.3. “to”屬性
? 表示消息的接收者。Jabber ID的“to”屬性一般是user@host/resource格式,user@host也可以被接受。如果接收者在線,通過user@host/resource方式解決,如果用戶不在線,直接發送離線存儲器。這個屬性是所有<message/>元素必須的。
? 例子:
<message to="romeo@montague.net/orchard">
<body>Wherefore art thou Romeo?</body>
</message>
3.3. <message/>中的子元素
? 下面的子元素是用來定義一個Jabber消息的上下文或數據元。
3.3.1. <body/>
? 這個元素包含消息的主要文本。<body/>元素只存在于一個<message/>元素中,并且只能包含明文。不過,它可以由其它子元素構成(如<error/>、<x/>)。
3.3.2. <error/>
? 當消息類型屬性被置為“error”時,這個元素將被使用。錯誤代碼被一個”type”屬性定義,這個”type”屬性包含代碼數,通過<error/>元素來包含一個這個錯誤的文本描述。<error/>元素必須包含在原始消息的<body/>中。下面的例子將演示,當Juliet向一個不存在的用戶發送“hi”消息后的包體:
? 例子:
<message
to="juliet@capulet.com"
from="flomeo@montague.net"
type="error">
<body>hi</body>
<error code="404">Not Found</error>
</message>
? 附文中有非法代碼與它們所定義的含義表。
3.3.3. <html/>
? <html/>元素結合XHTML名字空間(http://www.w3.org/1999/xhtml),為一個消息提供一個交替的名字空間,就像在email世界中規定同時發送普通文本與HTML版本的郵件消息一樣。這個功能使用的是W3C開發的基本XHTML格式(http://www.w3.org/TR/xhtml-basic/),關于Jabber在消息中的XHTML執行細節,請看Jabber消息的暫定格式規范(http://docs.jabber.org/draft-proto/html/xhtml.html)。所有XHTML的根元素都必須是<html xmlns=”http://www.w3.org/1999/xhmtl”></html>。這個根元素中,支持任何一個基本XHTML格式中定義的元素,但不是每一個元素可以通過即時消息的上下文來進行理解。
3.3.4. <subject/>
? 這是一個可選元素,包含消息的標題。
3.3.5. <thread/>
? 當一個Jabber客戶端發送一個”chat”類型的消息,將生成唯一的線程ID(通常是由發送者的Jabber ID和當前時間生成的一個hash)。消息發送者和接收者在聊天中后續的消息都包含一個<thread/>子元素,這個子元素包含原始線程ID。這使得消息發送者和接收者對回復進行認證并創建一個對話線程。下面的是例子:
<message
from="juliet@capulet.com/balcony"
to="romeo@montague.net/orchard"
type="chat">
<thread>AAC96FEFDE226C2C04BE8F2E19A2151B</thread>
<body>Art thou not Romeo and a Montague?</body>
</message>
<message
from="romeo@montague.net/orchard"
to="juliet@capulet.com/balcony"
type="chat">
<thread>AAC96FEFDE226C2C04BE8F2E19A2151B</thread>
<body>Neither, fair saint, if either thee dislike.</body>
</message>
3.3.6. <x/>
? <x/>元素作為一個擴展機制來使用,或發送從服務器發送命令給客戶端,或從一個客戶端發送命令到另一個客戶端。每次用到這個元素時,必須指明相關的XML名字空間。單一消息可以包含多個<x/>子元素實例。下列已定義的名字空間可以被<x/>子元素使用:
l ? ? ? jabber:x:autoupdate
l ? ? ? jabber:x:delay
l ? ? ? jabber:x:encrypted
l ? ? ? jabber:x:oob
l ? ? ? jabber:x:roster
這些名字空間在下面的Jabber名字空間中被更完整地描述。
下面是一個使用jabber:x:delay名字空間在加入的群組聊天室的顯示上下文的例子:
<message
type=’groupchat’
from=’cauldron@conference.witches.org’>
<body>Thrice the brinded cat hath mew’d.</body>
<x xmlns=’jabber:x:delay’
stamp=’10541031T21:43:40’>Cached In GC History</x>
</message>
4. <presence/>元素
? <presence/>元素提供關于一個Jabber實體的可用性信息。任何一個通過一個Jabber ID確認的實體可以與另一個實體進行在線狀態信息的通信,這種通信大多以訂閱在線狀態信息的方式進行。
? 所有實體表現出的在線狀態不是“可用”就是“不可用”。“可用”狀態表示發送者可以立即收到消息。“不可用”狀態表示發送者不能在當前時間收到任何數據。默認情況下,所有<presence/>元素除非包含type=”unavailable”屬性外,都表示“可用”。“可用”的更多特殊形勢通過<status/>和<show/>子元素進行指定。
4.1. “type”屬性
? <presence/>的“type”屬性根據不同目的使用。除了提示其它用戶本用戶的可用性狀態的“普通”用法外,還包括訂閱、取消訂閱、以及探測在線狀態信息。下面是“type”屬性的可用值:
4.1.1. type=”available”
? 如果沒有包含任何“type”屬性,在線狀態包將被設為type=”available”,用來提供用戶在線時的信息。一個type=”available”的在線狀態包通常包含一個<show/>元素以詳細說明Jabber實體的可用類型,以及一個<status/>元素,該元素包含人能看懂的關于該可用類型的描述。在線狀態包還可以包含一個<priority/>元素,來指明該連接的Jabber ID的優先級。
? 例子:
? <presence
from="juliet@capulet.com/balcony"
to="romeo@montague.net/orchard"/>
<show>away</show>
<status>Stay but a little, I will come again.</status>
</presence>
?
? <show/>元素的可用值為:
l ? ? ? away――Jabber用戶或實體在線,但不能馬上聯系上
l ? ? ? chat――Jabber用戶或實體在線并有興趣聊天
l ? ? ? dnd――Jabber用戶或實體在線,但不想被打擾(“dnd”表示“do not disturb”)
l ? ? ? xa――Jabber用戶或實體在線,但已經離開很長時間了(“xa”表示“extended away”)
<status/>可以包含任意特性數據,這些數據通常包含對于用戶狀態的描述,如,“開會中”是“away”的一個表現值,或者“忙于編碼”可以是“dnd”的一個表現。
4.1.2. type=”error”
? 當一個在線狀態包發送給一個不存在的JID時,或在發送在線狀態請求時發生一個錯誤時,服務器都將返回一個type=”error”的在線狀態包。
? 下面是一個例子(注意域名的類型):
<presence
? ? type="subscribe"
to="romeo@montague.nett"/>
? 回復的例子:
? <presence
? ? from="romeo@montague.nett"
to="juliet@capulet.com/balcony"
type="error">
<error code=’504’>Remote server timeout. Unable to deliver
packet.</error>
</presence>
4.1.3. type=”probe”
? 向一個特定實體(實體不能發送在線狀態消息給自己)發出在線狀態信息請求。服務器而非客戶端,進行一個探測請求。實際上,雖然Jabber客戶端也可以發送一個探測一個指定Jabber用戶是否在線的請求,但通常都是服務器端發出探測請求。注意,只有在發起請求的用戶在請求所對應的用戶的花名冊上,并且擁有“from”或“both”訂閱類型時,服務器才會發出探測請求。在下面的例子中,我們將看到我們的英雄Romeo向Juliet發出一個探測請求,Juliet所在服務器回復一個“狀態報告包”(包含jabber:x:delay名字空間中指明的上次在線狀態更新的時間戳)
? 探測請求的例子:
?
? <presence
from="romeo@montague.net"
to="juliet@capulet.com"
type="probe"/>
? 回復探測請求的例子:
? <presence
from="juliet@capulet.com/."
to="romeo@montague.net">
<status>Stay but a little, I will come again.</status>
<show>away</show>
? ? <x
xmlns="jabber:x:delay"
from="juliet@capulet.com/."
stamp="15310309T23:47:15"/>
</presence>
4.1.4. type=”subscribe”
? 發送一個請求,這個請求是接收者在其在線狀態改變時,自動發送在線狀態信息給發送者。
? 例子:
? <presence
from="romeo@montague.net"
to="juliet@capulet.com"
type="subscribe"/>
4.1.5. type=”subscribed”
? 發送一個消息,表明發送者接受了接受者對其再現狀態訂閱的請求。從現在起,當發送者的在線狀態信息改變時,服務器將會把狀態信息發送給接收者。
? 例子:
? <presence
from="juliet@capulet.com"
to="romeo@montague.net"
type="subscribed"/>
4.1.6. type=”unavailable”
? 例子:
? <presence
from="juliet@capulet.com"
to="romeo@montague.net"
type="unavailable">
<status>Disconnnected</status>
</presence>
4.1.7. type=”unsubscribe”
? 發送一個請求,表明接收者停止發送在線狀態信息給發送者。
? 例子:
?
<presence
from="juliet@capulet.com"
to="romeo@montague.net"
type="unsubscribe"/>
4.1.8. type=”unsubscribed”
? 這種類型的在線狀態包有兩個用途:
1. ? 發送一個表明發送者接受接收者關于不訂閱其在線狀態信息的請求的通知。服務器將不再發送發送者的在線狀態信息給接收者。
2. ? 拒絕一個訂閱請求。服務器將不再發送發送者的在線狀態信息給試圖訂閱其在線狀態信息的用戶。
例子:
<presence
from="romeo@montague.net"
to="juliet@capulet.com"
type="unsubscribed"/>
4.2. 其它<presence/>屬性
? 除了設置“type”屬性,還可以通過下列屬性修改<presence/>元素:
4.2.1. “from”屬性
標識在線狀態包的發送者。一般Jabber ID再“from”屬性中必須寫成user@host/resource的格式。從XML的觀點來說,這個屬性是所有<presence/>元素所必須的,而在實際應用中,都是服務器對該屬性進行添加和修改(防止一些欺騙的手段),因此客戶端開發者不需要考慮它。
例子:
<presence from="juliet@capulet.com/balcony"/>
4.2.2. “id”屬性
? 為在線狀態請求包配置唯一的驗證符。“id”屬性由Jabber客戶端或客戶庫(如Gabber或JabberCOM)生成,客戶端用其為在線狀態包的軌跡進行驗證。“id”屬性是可選的,并且不能用于系統其它任何地方。
? 例子:
? <presence to="romeo@montague.net/orchard" id="JCOM_86"/>
4.2.3. “to”屬性
? 標識在線狀態包的接收者。一般Jabber ID在“to”屬性中都是user@host/resource的格式,user@host的格式也是可以的,但當接收者在線時,它將轉化為user@host/resource。在Jabber的一般用法中,Jabber客戶端向服務器發出在線狀態包,服務器將這些在線狀態包發送到該用戶花名冊上所有的用戶。當一個Jabber客戶端發送的<presence/>元素中不含“to”屬性時,服務器將將其轉化為在線狀態包發送給指定的Jabber實體。下面的例子將演示這一過程。
? 發送給服務器的在線狀態的例子:
? <presence>
<status>Stay but a little, I will come again.</status>
<show>away</show>
</presence>
服務器發給指定用戶的在線狀態例子:
<presence
to="romeo@montague.net/orchard"
from="juliet@capulet.com/balcony">
<status>Stay but a little, I will come again.</status>
<show>away</show>
</presence>
4.3. <presence/>的子元素
? 下面的元素用于<presence/>協議。
4.3.1. <priority/>
? 在Jabber中,根據Jabber知道的設備數或位置數,一個用戶可以建立相同數量的連接。用戶可以給每一個資源賦予一個數字優先級(通過對指派給該資源的Jabber客戶端進行設置),這個優先級與<presence/>元素的子元素<priority/>方法進行通信。
? 當在線狀態包發送到服務器后,服務器有能力決定哪一個連接資源需要指派一個單一的Jabber ID,該資源將收到發往該Jabber ID的消息,這是因為數字最高的資源是默認或第一資源。如果最高優先級的資源不可用,消息和其它Jabber通信將發送給次高優先級的資源(當其它資源都不可用時,一個沒有從默認數到0的優先級的客戶端,也可以成為第一資源)
? 舉例來說,Julie可以通過兩個資源:the balcony 和 the chamber連接她的帳號juliet@capulet.com。如果“balcony”資源的優先級被設置為“2”,而“chamber”資源的優先級被設為“1”,而且兩個資源都可以連接,消息將發送到juliet@capulet.com/balcony,而不是juliet@capulet.com/chamber。
4.3.2. <show/>
? 可選的<show/>元素告訴Jabber客戶端如何顯示一個用戶的在線狀態。<show>標簽是一個典型的<status>標簽的伴隨標簽,<status>標簽包含更多在線狀態改變理由的描述信息。如果<show/>元素不在<presence/>元素中,Jabber接收客戶端將指明該用戶處于“普通”狀態。下面是四個可選項:
標簽
含義
<show>chat</show>
該客戶可以馬上聯系上
<show>away</show>
該客戶在線,但剛剛離開(如吃午飯,開會)
<show>xa</show>
該客戶在線,但已經處于非活動狀態很長時間了。
<show>dnd<show>
該用戶處于謝絕打擾的模式
4.3.3. <status/>
? <status/>元素包含更多關于用戶在線狀態的描述。大多數Jabber客戶端都包含一些<status/>元素的默認設置;另外,它們還允許我們提供富有個性的描述如“我在吃午飯”或者“釣魚中”。
4.3.4. <x/>
<x/>元素作為一個擴展機制來使用,或發送從服務器發送命令給客戶端,或從一個客戶端發送命令到另一個客戶端。每次用到這個元素時,必須指明相關的XML名字空間。單一消息可以包含多個<x/>子元素實例。下列已定義的名字空間可以被<x/>子元素使用:
l ? ? ? jabber:x:autoupdate
l ? ? ? jabber:x:delay
l ? ? ? jabber:x:encrypted
l ? ? ? jabber:x:oob
l ? ? ? jabber:x:roster
這些名字空間在下面的Jabber名字空間中被更完整地描述。
5. <iq/>元素
? 信息/查詢(IQ)在Jabber中在兩個實體間構建一個根本的會話,并且允許實體間來回傳送XML格式的請求和響應。信息/查詢主要的用處是取得或設置公共的用戶信息,比如名字,電子郵件,地址等等。但它的靈活設計使得任何種類的會話都可以發生。任何通過一個Jabber ID標識的實體都能通過一個IQ與其它實體進行會話。
5.1. “type”屬性
? <iq/>元素的“type”屬性用于決定信息/查詢是請求還是響應。下面是“type”屬性的可用值:
5.1.1. type=”error”
? 表示查詢失敗。實際錯誤在<iq/>元素的<error/>子元素中描述。
? 例子:
?
? <iq type="error" to="romeo@montague.net">
<error code="403">Forbidden</error>
</iq>
5.1.2. type=”get”
? 找回指派給一個查詢名字空間的信息。如果沒有設置屬性,默認情況,這個屬性包含在查詢中。一個type=”get”的<iq/>元素由一個子元素構成,這個子元素通常是<query>,但也可以是<vcard/>或另一個已有的子元素。不過,指定的子元素必須左空,以便接收一個用戶所需提供的信息的空間的清單。一個成功的get查詢的結果type=”result”的<iq/>元素,是元素嵌套在包含了所需信息的指定子元素(如<query>或<vcard/>)。
? 例子:
? <iq type="get">
<vCard xmlns="vcard-temp"/>
? </iq>
5.1.3. type=”result”
? 表示<iq/>包是一個type=”get”或type=”set”的<iq/>查詢的成功響應。這個成功查詢的結果是一個type=”result”的<iq/>元素,該元素嵌套在一個包含所查詢的信息的子元素中(如<query>、<vcard/>)。一個成功的查詢或獲取查詢結果的返回是一個空的type=”result”的<iq/>元素。一個不成功的返回是一個type=”error”的<iq/>元素。<iq type=”result”/>通常與“id”屬性的獲取、設定查詢有關。
例子:
? <iq type="result">
<vCard version="3.0" xmlns="vcard-temp">
vCard data goes here
</vCard>
</iq>
5.1.4. type=”set”
? 表示<iq/>包是對設值或更改現有數據值。一個type=”set”的<iq/>元素總是包含一個指定的子元素,通常是<query>,也可以是<vcard/>或者其它可以接受的子元素。一個設置命令查詢的成功返回是一個空的type=”result”的<iq/>元素。
? 例子:
? <iq type="set">
<vCard version="3.0">
vCard data goes here
</vCard>
</iq>
5.2. 其它<iq/>屬性
? 除了“type”屬性外,IQ元素還可以通過下面的屬性進行修改。
5.2.1. “from”屬性
? 表示iq包的發送者。從XML觀點來說,這個屬性是所有<iq/>元素所必須的,實際應用中這個屬性是服務器來增加和修改的(為防止某些欺騙),因此客戶端的開發人員不需要過多關注這個屬性。
? 例子:
?
? <iq from="romeo@montague.net"/>
5.2.2. “id”屬性
? 一個iq包只有唯一的標識。Jabber客戶端或客戶庫生成“id”屬性,客戶端通過它來標識<iq/>包,以完成對<iq/>包的跟蹤(如:一個type=”result”對應一個type=”get”或type=”set”)。“id”屬性是可選的,并且不能用于系統的其它地方。
? 例子:
? <iq type="get" from="juliet@capulet.com/balcony" id="JCOM_87"/>
<iq type="result" to="juliet@capulet.com/balcony" id="JCOM_87"/>
5.2.3 “to”屬性
? 表示iq包的接收者。在Jabber客戶端,對應“to”屬性的Jabber ID的格式為user@host/resource。user@host也是可以的,如果用戶在線,user@host將被置換成user@host/resource,如果用戶不在線,user@host將被直接指向一個離線模塊(對于類似服務器端網關這種非用戶實體,情況又有所不同,因為它們不擁有資源,并且只是簡單通過Jabber ID的一個“server”端口進行標識。Jud.jabber.org——Jabber用戶目錄就是這樣一個例子)。如果<iq/>包沒有<to>屬性,服務器將對該包進行處理。
? 例子:
? <iq to="juliet@capulet.com/balcony">
5.3 <iq/>的子元素
? 下面介紹<iq/>元素的子元素。
5.3.1. <error/>
? 當iq的屬性類型被設置為“error”時,將用到本屬性。錯誤代碼根據一個含有錯誤數的“type”屬性進行定義,<error/>員司包含該錯誤的文本描述。比如,下面就是一個壞請求:
?
? <error code="400">Bad Request</error>
?
? 在附錄中,列有錯誤編碼及其對應的錯誤描述。
5.3.2. <key/>
? <key/>元素為客戶端-服務器之間交互提供一層安全保護。它被用戶jabber:iq:register和jabber:iq:search名字空間中。
? 當一個客戶端發起一個與服務其之間的交互時,服務器將發送一個包含一個唯一值的<key>給客戶端。客戶端在返回<iq type=”set”/>的消息中,包含上訴唯一值到<key/>子元素中。這樣,服務器就認為該客戶端時接收到原來密碼的同一實體。
5.3.3. <query/>
? <iq/>元素中的<query/>子元素定義所執行的查詢的類型。特殊情況下,查詢可以擁有一個特殊的名字空間,這個名字空間是一個通過“xmlns”屬性定義的<query/>子元素。一個<iq/>元素中只能有一個<query/>子元素。
? 下面的例子是當我通過我的Linux機器上的Grabber客戶端登陸到服務器上,將出現的XML。
<iq type="set">
<query xmlns="jabber:iq:auth">
<username>stpeter</username>
<resource>Gabber</resource>
<digest>f1e881517e9917bb815fed112d81d32b4e4b3aed</digest>
</query>
</iq>
就象你看到的那樣,認證查詢通過客戶端認證名字空間(jabber:iq:auth)向服務器發送認證信息。一般,Jabber核心協議保留jabber:iq:*這樣的名字空間。而開發者可以通過增加jabber:iq:*名字空間對Jabber核心進行擴展。這些將在下面的名字空間中進行更完整的描述。
一個空<query/>子元素可以與<iq type=”get”>元素一起發送,這樣可以找回與<query/>子元素中指定的名字空間相關的一個Jabber實體的信息。比如,找回一個客戶端的花名冊(“聯系人名單”),下面的XML可以被發送:
<iq to="juliet@capulet.com/balcony" type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
6. 名字空間
? 現面是Jabber中的標準名字空間:
l ? ? ? jabber:iq:agent——代理工具
l ? ? ? jabber:iq:agents——有效的代理組
l ? ? ? jabber:iq:auth——簡單用戶認證
l ? ? ? jabber:iq:autoupdate——版本更新申請
l ? ? ? jabber:iq:browse——Jabber瀏覽
l ? ? ? jabber:iq:conference——一般會議
l ? ? ? jabber:iq:gateway——用戶地址網關
l ? ? ? jabber:iq:last——上次使用時間
l ? ? ? jabber:iq:oob——綁定數據輸出
l ? ? ? jabber:iq:private——私有數據存儲
l ? ? ? jabber:iq:register——注冊請求
l ? ? ? jabber:iq:roster——花名冊(聯系人名單)管理
l ? ? ? jabber:iq:search——用戶數據庫查詢
l ? ? ? jabber:iq:time——客戶端時間
l ? ? ? jabber:iq:version——客戶端版本
l ? ? ? jabber:x:autoupdate——版本通知申請
l ? ? ? jabber:x:conference——會議邀請
l ? ? ? jabber:x:delay——顯示的對象
l ? ? ? jabber:x:encrypted——加密的消息
l ? ? ? jabber:x:envelope——消息封套
l ? ? ? jabber:x:event——消息事件
l ? ? ? jabber:x:expire——消息終止
l ? ? ? jabber:x:oob——綁定數據(文件傳輸)輸出
l ? ? ? jabber:x:roster——內部的花名冊條目
l ? ? ? jabber:x:signed——標記的在線狀態
l ? ? ? vcard-temp——臨時的vCard
下面將詳細介紹這些名字空間的細節。
6.1. jabber:iq:agent——代理工具
? 代理工具名字空間包含一個代理的所有工具。jabber:iq:angents查詢通常用于注冊到一個指定的服務、代理、傳輸器。
? 它也可能檢驗一個指定代理的所有工具細節。比如,一個客戶端可以決定一個開放的注冊是否可以進行。
? 例子:
? <iq id="wjAgent" type="result" from="Jabber.org">
<query xmlns="jabber:iq:agent">
<agent jid="aim.jabber.org">
<name>AIM Transport</name>
<description>This is the AIM Transport</description>
<transport>AIM/AOL ScreenName</transport>
<service>aim</service>
<register/>
</agent>
</query>
</iq>
6.2. jabber:iq:angents——可用的代理列表
? 可用代理列表名字空間包含一組實體,這些實體擁有一些特殊工具,并能夠為另一個實體提供服務。大多數情況下,可用代理列表是用來顯示一臺服務器上的可用傳輸器列表。
? 注意:這個名字空間被jabber:iq:browse的支持者所反對(??)。
? 例子:
? <iq id="wjAgents" type="result" from="jabber.org">
<query xmlns="jabber:iq:agents">
<agent jid="users.jabber.org">
<name>User Directory</name>
<description>
You may register and create a public searchable
profile, and search for other registered Jabber
users.
</description>
<service>jud</service>
<register/>
<search/>
</agent>
<agent jid="aim.jabber.org">
<name>AIM Transport</name>
<description>This is the AIM Transport</description>
<transport>AIM/AOL ScreenName</transport>
<service>aim</service>
<register/>
</agent>
</query>
</iq>
6.3. jabber:iq:auth——簡單客戶端認證
簡單客戶認證名字空間是對客戶端進行認證的一個簡單機制,它為客戶端到服務器之間的連接創建一個資源。
認證成功返回一個type=”result”的IQ響應。不成功,就返回一個錯誤IQ元素。
如果沒有發送名字空間或密碼,如果服務器允許,服務器將創建一個匿名資源。
例子:
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<password>secret</password>
<resource>balcony</resource>
</query>
</iq>
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<digest>a5e052c48c455bf21d937ccf17225916d9486b09</digest>
<resource>balcony</resource>
</query>
</iq>
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<hash499>secret</hash499>
<resource>balcony</resource>
</query>
</iq>
6.4. jabber:iq:autoupdate——版本更新申請
? 版本更新申請名字空間允許客戶端對所有可用軟件更新進行申請請求。
? 例子:
<iq type="get" to="jabber.org" id="1">
<query xmlns="jabber:iq:autoupdate"/>
</iq>
6.5. jabber:iq:browse——Jabber瀏覽
? Jabber瀏覽名字空間的作用是,一是為Jabber世界中已有的Jabber IDs增加結構的一個途徑,一是發現為不同Jabber實體提供的服務或應用。一個Jabber瀏覽的基本概念就是一個jid-type(類似文件的一個模擬類型的概念)。下面是想象中的最高級別的jid-types,不過隨著時間的推移,一些其它的邏輯將被增加進來:
l ? ? ? 應用
l ? ? ? 會議
l ? ? ? 標題
l ? ? ? 關鍵字
l ? ? ? 回報
l ? ? ? 服務
l ? ? ? 用戶
上面每一個范疇都有一個子類列表,如用戶/客戶端,或用戶/設備(“客戶端”或“設備”只是一個“資源”的概念),會議/irc,服務/icq,標題/庫存。一般的,通過使用jabber:iq:browse名字空間你將擁有一個與上述某一jid-type范疇相對應的元素,這個元素通常有一個指定子類型的“type”屬性。
Jabber:iq:browse的一個用戶就是代替jabber:iq:agents名字空間來列出一個服務器上所對應的代理或其它服務。下面是一個瀏覽服務器的例子:
Jabber客戶端發送:
<iq type="get" to="jabber.org">
<query xmlns="jabber:iq:browse"/>
</iq>
Jabber服務器返回:
<iq type="result" from="jabber.org">
<service
type="jabber"
jid="jabber.org"
xmlns="jabber:iq:browse>
<service
type="jud"
jid="users.jabber.org"
name="Jabber User Directory">
<ns>jabber:iq:register</ns>
<ns>jabber:iq:search</ns>
</service>
<service
type="aim"
jid="aim.jabber.org"
name="AIM Transport">
<ns>jabber:iq:register</ns>
<ns>jabber:iq:search</ns>
</service>
<conference
type="private"
jid="conference.jabber.org"
name="Private Chatrooms">
</service>
</service>
</iq>
在會議中的一個例子:
<iq type="set" to="room@server">
<conference xmlns="jabber:iq:browse" name="Room Name">
<user jid="room@server/jidhash" name="nick1"/>
<user jid="room@server/jidhash" name="nick2"/>
</conference>
</iq>
6.6. jabber:iq:conference——一般會議
? 一般會議名字空間提供一個會議室的機制(如群組聊天室),并提供該會議室的入口。這個名字空間與</iq>元素配套使用來獲得一個會議室的信息,包括要求加入這個會議室的請求信息,以及為這個會議室設置信息(通常是為了加入這個房間)。一個普通進入房間的請求將和下面的類似:
1. ? 想要加入的房間提交一個type=”get”的請求。這個XML將是下面的形式:
<iq type="get" to="room@server">
<query xmlns="jabber:iq:conference"/>
</iq>
2. ? 接受來自要加入的房間的type=”result”的iq響應,其中有進入房間所需要的參數。這個XML將是下面的形式:
<iq type="result" from="room@server">
<query xmlns="jabber:iq:conference">
<nick/>
<secret/>
<privacy/>
<name>Room Name</name>
</query>
</iq>
這里所有的請求元素的子元素都是可選的。昵稱(nickname)元素表示進入房間需要一個昵稱。密鑰(secret)元素表示進入房間的用戶需要提供一個密碼。獨處(privacy)元素表示如果用戶在一個type=”set”(下面可以看到例子)的iq包中提供這樣的元素,會議服務器將隱藏用戶的真實Jabbere ID。名字(name)元素是房間的名字(用jabber:iq:browse瀏覽房間時可以看到同樣的房間名)。
3. ? 發送當前狀態給要加入的房間。XML如下:
<presence to="room@server"/>
4. ? 想要加入的房間提交一個type=”set”的iq包以及進入所需信息。XML如下:
<iq type="set" to="room@server">
<query xmlns="jabber:iq:conference">
<nick>mynick</nick>
<nick>mysecondnick</nick>
<secret>thesecret</secret>
</query>
</iq>
注意在用戶第一個選擇被接受時,用戶可以提交多個昵稱。如果用戶沒有提供昵稱,服務器將指派一個昵稱給用戶。
5. ? 收到你加入的房間的通知,這個iq以下面的格式返回:
<iq type="result" from="room@server">
<query xmlns="jabber:iq:conference">
<id>room@server/uniqueidnumber</id>
<nick>mynick</nick>
</query>
</iq>
這個唯一的ID號是用戶Jabber ID的一個哈希。
6.7. jabber:iq:gateway——用戶地址網關
? 一般通過一個網關或傳輸器(比如AIM傳輸器)來實現與非Jabber網絡用戶的通信,每一個非Jabber網絡都可能擁有唯一的用戶地址,這個地址可能和Jabber IDs并不統一。用戶地址網關就是解決這個問題的,它使得Jabber客戶端向非Jabber網絡用戶發出訂閱時給出正確Jabber IDs變得很容易。這些通過對用戶進行提示和會話,引導用戶提供創建一個正確Jabber ID所需信息來實現。下面將演示這種普通的交互:
1. ? 客戶端向網關發出帶有jabber:iq:gate名字空間查詢的iq get:
<iq type="get" to="aim.jabber.org">
<query xmlns="jabber:iq:gateway"/>
</iq>
2. ? 服務器返回一個包含請求批準及其描述文本的iq:
<iq type="result" from="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<desc>
Please enter the AOL Screen Name of the person
you would like to contact.
</desc>
<prompt>Screen Name</prompt>
</query>
</iq>
3. ? 客戶端向網關發送一個包含指定信息的iq set:
<iq type="set" to="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<prompt>Joe Cool</prompt>
</query>
</iq>
4. ? 服務器返回一個包含正確Jabber ID的iq result
<iq type="result" from="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<jid>JoeCool@aim.jabber.org</jid>
</query>
</iq>
6.8. jabber:iq:last——最后一次在線時間
最后一次在線時間名字空間提供一個標準的方法,通過這個方法可以查詢一個Jabber實體一個或多個服務更新時間,或者一個客戶最后一次連接(或活動)到一臺服務器上的時間。每一次返回的值都是一個秒的數目。進行查詢的實體可以通過下面的法則解釋獲取的信息:
l ? ? ? user@server/resource——用戶最后一次活動的時間
l ? ? ? user@server——用戶最后一次連接的時間
l ? ? ? server——服務器最后一次啟動的時間
例子(服務器):
<iq type="get" to="jabber.org">
<query xmlns="jabber:iq:last"/>
</iq>
<iq type="result" to="stpeter@jabber.org/Gabber" from="jabber.org">
<query xmlns="jabber:iq:last" seconds="124933"/>
</iq>
例子(客戶端):
<iq type="get" to="jer@jabber.org">
<query xmlns="jabber:iq:last"/>
</iq>
<iq type="result" to=stpeter@jabber.org/Gabber from="jer@jabber.org">
<query xmlns="jabber:iq:last" seconds="5024">
Disconnected
</query>
</iq>
6.9. jabber:iq:oob——綁定數據輸出
? 綁定數據輸出名字空間為客戶端-客戶端的文件傳輸提供一個標準方法,通過服務器的傳輸/代理的傳輸器實現一個特殊的名字空間:
例子:
<iq type="set" to="horatio@denmark.com" id="file_1">
<query xmlns="jabber:iq:oob">
<url>http://denmark.com/act4/letter-1.html</url>
<desc>There’s a letter for you sir.</desc>
</query>
</iq>
6.10. jabber:iq:private——私有數據存儲
? 私有數據存儲名字空間是Jabber服務器上存儲私有數據的一個機制。存儲的數據可以是任何合法的XML數據。在服務端存放客戶端的當前狀態信息是這個名字空間的典型用法。
? 例子1(客戶端存儲私有數據):
<iq type="set" id="1001">
<query xmlns="jabber:iq:private">
<winjab xmlns="winjab:prefs">
<defaultnick>Hamlet</defaultnick>
</winjab>
</query>
</iq>
例子2(客戶端找回私有數據):
<iq type="get" id="1002">
<query xmlns="jabber:iq:private">
<winjab xmlns="winjab:prefs"/>
</query>
</iq>
另外,對于私有數據存儲,1.4版服務器支持服務器上所有有效名字空間(以“jabber”開頭的名字空間保留,為Jabber系統進行調用)的XML數據。這個數據存在向服務器端發送type=”set”的iq包的用戶的花名冊中。
例子1(客戶端保存公有數據):
<iq type="set" id="1003">
<query xmlns="stpeter:public:favorites">
<fav_things>
<food>Thai</food>
<color>blue</color>
<composer>Bach</composer>
</fav_things>
</query>
</iq>
例子2(客戶端找回公有數據):
<iq type="get" id="1004">
<query xmlns="stpeter:public:favorites">
<fav_things/>
</query>
</iq>
6.11. jabber:iq:register——注冊請求
注冊請求名字空間對一個或多個服務進行注冊。它也被用來更新或刪除一個注冊。
例子:
<query xmlns="jabber:iq:register">
<instructions>
Some instructions to be displayed when the
user is filling out the form.
</instructions>
<username/>
<password/>
<email/>
<date/>
<key/>
</query>
6.12. jabber:iq:roster——聯系人名單管理
聯系人名單管理名字空間是客戶端用來管理他們的花名冊的,該花名冊保存在服務器上,這樣用戶可以在任何地方得到它。花名冊是該帳號上所有訂閱信息的命令列表,包括用戶昵稱和聯系列表。當用戶從任何一個資源登陸上來,服務器將把花名冊發送給用戶。
花名冊是一個條目的列表。每一個條目元素都有描述它的屬性。每一個條目元素都包含它所屬組的組元素。下面是描述<item/>元素的屬性:
l ? ? ? “jid”是條目的Jabber ID
l ? ? ? “subscription”所有和本條目相關的訂閱所對應的用戶的當前狀態。它可以是“none”(不可訂閱),“to”(有一個發到該條目的訂閱),“from”(從該條目發送一個訂閱給我們),“both”(to、from),或者“remove”(從花名冊上刪除一個條目)。
l ? ? ? “ask”是對這個條目的一個請求的當前狀態。Subscribe表示請求對該條目進行訂閱,它的值就是,Unsubscribe表示取消訂閱。
l ? ? ? “name”表示昵稱
通過使用一個<iq type=”set”/>,一個Jabber客戶端可以控制用戶的JabberID,名稱屬性,群組元素,并且可以在聯系人名單上創建或刪除聯系人。服務器根據客戶端對當前狀態訂閱請求的響應來管理其它所有屬性。
訂閱請求的例子:
<iq type="set" id="uniquevalue">
<query xmlns="jabber:iq:roster">
<item jid="romeo@montague.net"
name="Romeo"
subscription="none"
ask="subscribe">
<group>friends</group>
</item>
</query>
</iq>
當一個花名冊條目在服務器上改變時,服務器將把這個改變推送給一個用戶。這個推送是一個普通的從服務器發送到客戶端的<iq type=”set”/>包。下面是一個例子:
<iq type="set">
<query xmlns="jabber:iq:roster">
<item jid="romeo@montague.net" subscription="both"/>
</query>
</iq>
? 在上面的例子中,服務器推送給客戶端一個花名冊,表明該用戶對romeo@montague.net的當前狀態信息有訂閱。一個花名冊推送可能發生一個連接的任何時間中,該連接是另一個連接修改資源或服務器(修改訂閱屬性)的結果。客戶端只有使用花名冊推送來改變花名冊的顯示。但不是每次花名冊推送都對用戶起作用。
6.13. jabber:iq:search——用戶數據庫查詢
? 任何一個代理都可以成為一個查詢代理。例如,JUD查詢Jabber用戶,ICQ傳輸器查詢ICQ用戶。
? 用戶發送一個進行可查詢域的Get請求:
<iq
type="get"
id="1001"
to="users.jabber.org"
from="romeo@montague.net/orchard">
<query xmlns="jabber:iq:search"/>
</iq>
? 查詢代理返回一個可查域:
<iq type="result" id="1001" from="users.jabber.org">
<query xmlns="jabber:iq:search">
<instructions>Fill in a field to search for any
matching Jabber User
</instructions>
<name/>
<first/>
<last/>
<nick/>
<email/>
<key>067941fd96a6a2752a21abcb6d737130dd51dd50</key>
</query>
</iq>
? 注意這些域是以提示的形式返回。為了傳輸的安全還包含一個密鑰(下面會看到)。用戶現在可以在允許的域內進行標準的查詢了。用戶發回一個Set請求給代理進行實際查詢:
? <iq
type="set"
id="1002"
to="users.jabber.org"
from="romeo@montague.net/orchard">
<query xmlns="jabber:iq:search">
<last>Capulet</last>
<key>11b830e604215c3a2a24652c69fd4efa2a7a5746</key>
</query>
</iq>
? 服務器根據查詢返回結果:
<iq type="result" id="1002" from="users.jabber.org">
<query xmlns="jabber:iq:search">
<item jid="juliet@capulet.com">
<name>Juliet Capulet</name>
<first>Juliet</first>
<last>Capulet</last>
<nick>juliC</nick>
<email></email>
</item>
<item jid="sampson@capulet.com>
<name>Sampson Capulet</name>
<first>Sampson</first>
<last>Capulet</last>
<nick>sammy</nick>
<email></email>
</item>
</query>
</iq>
? 注意有兩套items標記含有指定信息。這是因為通過代理發送返回有兩種方法:
l ? ? ? 單一返回標簽
l ? ? ? 多個“pushed”到用戶的標簽,類似花名冊推送,如在一個時間上的一個記錄。
發送的返回的樣式是查詢代理的一個工具。比如:
<iq type="set" from="icq.jabber.org" id="1003">
<query xmlns="jabber:iq:search">
<item jid="7090245@icq.jabber.org">
<email>juliet@capulet.com</email>
<nick>juliC</nick>
<given>Juliet</given>
<family>Capulet</family>
</item>
</query>
</iq>
多個查詢結果通過服務器進行推送。當所有數據發送完畢,服務器將發送下面的返回結果:
<iq type="result" from="icq.jabber.org" id="1003">
<query xmlns="jabber:iq:search"/>
</iq>
客戶端接收到多個“sets”,每一個都被記錄,最后收到一個表示“數據結尾”的“返回”。在每一個<item>標簽中,JID屬性都被強制帶上。
例子:
<iq
type="get"
id="1001"
to="users.jabber.org"
from="juliet@capulet.com">
<query xmlns="jabber:iq:search"/>
</iq>
6.14. jabber:iq:time——客戶端時間
? 客戶端時間名字空間是客戶端改變當前時間的一個標準方法。
? 例子:
<iq type="result" from="stpeter@jabber.org">
<query xmlns="jabber:iq:time">
<utc>20010214T18:55:06</utc>
<display>2/15/00 4:55:06 PM</display>
</query>
</iq>
6.15. jabber:iq:version——客戶端版本
? 客戶端版本名字空間是得到另一個用戶的客戶端的版本信息的一個標準方法。
? 例子:
<iq type="result" from="stpeter@jabber.org/Gabber">
<query xmlns="jabber:iq:version">
<name>Gabber</name>
<version>0.8.1 (Powered by: jabberoo 1.0.0</version>
<os>Linux 2.2.16-22 i686</os>
</query>
</iq>
6.16. jabber:x:autoupdate——應用程序版本通知
? 版本更改申請名字空間使服務器可以在一個應用的新版本可用時通知客戶端。
? 例子:
?
<message from="winjab.sourceforge.net">
<x xmlns="jabber:x:autoupdate">A new version of WinJab
is available, see http://winjab.sourceforge.net/
</x>
</message>
6.17. jabber:x:conference——會議邀請
? 會議邀請名字空間使用戶可以邀請其它Jabber用戶到指定會議室。相關聯信息——該會議室的Jabber ID,內嵌在一個消息的<x/>元素中。
? 例子:
<message to="romeo@montague.net" from="juliet@capulet.com">
<body>Wherefore art thou Romeo?</body>
<x xmlns="jabber:x:conference" jid="balcony@conference.capulet.com/>
</message>
6.18. jabber:x:delay——標記對象延時
? 標記對象延時名字空間是消息和當前狀態信息的時間戳信息,其中,當一個Jabber實體不在線時,當前狀態信息可以保存并在稍后發送。當實體上線時,包含的信息標記對象延時名字空間使Jabber客戶端顯示出該包體最早產生的時間,而不是它發送給Jabber實體的時間。
? 例子:
<message
type=’groupchat’
from=’cauldron@conference.witches.org’>
<body>Thrice the brinded cat hath mew’d.</body>
<x xmlns=’jabber:x:delay’
stamp=’10541031T21:43:40’>Cached In GC History</x>
</message>
6.19. jabber:x:encrypted——加密消息
? 加密消息名字空間用來支持使用公共密鑰(一般通過客戶端使用PGP或GPG,服務端用同樣的名字空間進行加密來實現)加密的消息交互。一個相關的名字空間,jabber:x:signed,用來進行當前狀態信息的加密。
? 例子:
<message from=’juliet@capulet.com/balcony’ to=’romeo@montague.net/orchard’>
<body>This Message is Encrypted</body>
<x xmlns=’jabber:x:encrypted’>
hQEOA7ucqu53AhlPEAP/ZbU6oPnRAbIcUxMK1XRVnkgZ/Agtq1tcTQuEZxbpZLl4
C/4psQGLgBU5h5Y3/khxtJTPXKn1izyc+DRZ8hqn2p4mwC8ioKTBJ6P6dfEpQEyt
a4bimM5fqdeh4gRkMhwThRSJxBCJBVVWFEViu+0KlHHB5AeeL4qwRGb2dhGjIgQD
/R9x0D0qtgBGwf/TVnRGZYRX7epxCNuNDEYKZSs4LEoTPL8CVsAWOzS2QgS0GBqt
tFDKId6XaNu36dB2D8VHdxQnI8RtHo9pfTYDaXWB3dMGTt896iEO/sTuucYObf3s
K5Kygg0uWpBpvQPj8Y041FhnUBz8DRGCnuFLQxCI6ch4ybauXfOKNOGDQwmsnJZm
6OaeVFUwdsedI3c6VdQtodnWVutckR5BOjnn0VqnhrVTu7cp6VXrrRK4g9atPEe6
C4R/MilBjzIJBcET0jhWuAyiBo3gN/6IqYRZNSXL9ZqGPJwNTlYim1EHN3qBqiUw
zUMamEoRzcusn80Z7kylve5ujIeSD/pVwoawHHvLp92kO2hd0yGD0UrWSfKU1o6y
EY8yhZ5P1v02pIKigAUI2c6LTDxt/KhSxQ==
=fijN
</x>
</message>
6.20. jabber:x:envelope——消息信封
? 消息信封名字空間是表明消息有更多的尋址方式,如聯合email進行的尋址。下面是一些所支持的名字空間:
l ? ? ? to
l ? ? ? cc
l ? ? ? replyto
l ? ? ? from
l ? ? ? forwardedby
上述每一個元素都帶有一個”jid”屬性來標識Jabber實體是發送、中轉、還是收到消息。
例子:
<message from=’juliet@capulet.com/tomb’ to=’romeo@montague.net/tomb’>
<body>And there I am. Where is my Romeo?</body>
<x xmlns=’jabber:x:envelope’>
<to jid=’romeo@heaven.org>Romeo</to>
<forwardedby jid=’root@heaven.org>God</forwardedby>
</x>
</message>
6.21. jabber:x:event——消息事件
? 消息時間名字空間是標識一條消息的狀態的一個機制。現在,事件與一條消息如下般相關聯:
l ? ? ? <composing/>——個用戶正在對消息進行回復
l ? ? ? <delivered/>——發送給指定接收者的消息
l ? ? ? <displayed/>——顯示給指定接收者的消息
l ? ? ? <offline/>——為離線進行存儲的消息
對于客戶端來說,這些消息事件的支持是可選的,而且,只有在另一用戶在聊天中發出請求,這些消息事件才會被發送。不同的Jabber客戶端將對當前狀態消息事件進行不同的顯示。
對消息通知的請求的例子:
<message
from="juliet@capulet.com/balcony"
to="romeo@montague.net/orchard"
id="1001">
<body>By whose direction found’st thou out this place?</body>
<x xmlns="jabber:x:event">
<composing/>
</x>
</message>
發送消息通知的例子:
<message from="romeo@montague.net/orchard" to="juliet@capulet.com/balcony">
<body>By whose direction found’st thou out this place?</body>
<x xmlns="jabber:x:event">
<composing/>
<id>1001<id/>
</x>
</message>
? 可以同時請求多個消息事件。
6.22. jabber:x:expire——消息到期
? 消息到期名字空間是說明一條消息擁有一個有限的存活事件的一個簡單擴展。如果消息被離線存儲,而到了到期時間,服務器將不再發送該消息。如果一條消息為預覽就進行發送,Jabber客戶端可以選擇不顯示該消息。“secondes”屬性定義消息發送的事件。
? 例子:
<message from="sailor@denmark.com" to="horatio@denmark.com">
<body>There’s a letter for you sir</body>
<x xmlns="jabber:x:expire" seconds="3600"/>
</message>
6.23. jabber:x:oob——綁定數據輸出
? 綁定數據輸出名字空間使用戶可以通過交換一個標準的URL來實現文件傳輸的目電。使用jabber:x:oob的URLs交換可以包含任一消息(在一個<x/>子元素內),感覺就像email里的附件一樣。多個附件可以包含在同一個消息中。
? 例子:
<message from="sailor@denmark.com" to="horatio@denmark.com">
<body>URL Attached.</body>
<x xmlns="jabber:x:oob">
<url>http://denmark.com/act4/letter-1.html</url>
<desc>There’s a letter for you sir</desc>
</x>
</message>
6.24. jabber:x:roster——內置的花名冊條目
? 內置的花名冊條目使用戶可以在一個消息中包含花名冊條目,這樣很容易在用戶之間發送聯系方式。每一個花名冊條目都包含在一個<x/>的一個<item/>子元素中。這個<x/>元素一般用在一個<message/>元素中,但這不是必須的。
? 例子:
<message to="hamlet@denmark.com">
<body>
Here are some new Jabber users
to add to your contact list!
</body>
<x xmlns="jabber:x:roster">
<item jid="claudius@denmark.com" name="King">
<group>Royalty</group>
</item>
<item jid="horatio@denmark.com" name="Horatio">
<group>Friends</group>
</item>
<item jid="fortinbras@norway" name="Prince Fortinbras"/>
</x>
</message>
6.25. jabber:x:signed——有符號的當前狀態
? 有符號的當前狀態名字空間用來支持交換使用公共密鑰(客戶端使用PGP或GPG,服務端使用同樣的名字空間進行加密)加密的當前狀態信息。一個相關的名字空間,jabber:x:encrypted用來支持加密消息。
? 例子:
<presence from=’juliet@capulet.com/balcony’ to=’romeo@montague.net/orchard’>
<show>away</show>
<status>be back later</status>
<x xmlns=’jabber:x:signed’>
iD8DBQA6kasv0xpc2/POfPkRAnz0AJ9UEYYWWSReddIKk3AYMfTFtqQDJwCfbcLd
JcSUOR0FlS+rDFjAPaSMgSM+iNaNm
</x>
</presence>
6.26. vcard-temp——臨時vCard
? vCard格式是一個“電子商務卡的標準格式,通過使用通過互聯網進行個人數據的直接交換,如同在非互聯網下的環境一樣”。由于XML的vCard的格式還沒有標準化,Jabber.org項目在XML的vCard標準建立之前,暫時設置了這樣一個臨時名字文件。由于這幾年在vCard的XML的官方標準的指定上沒有任何進步,Jabber.org開發者專門為這個項目創建了一個項目吸引Jabber社區外其它開發者的注意。因此,最后的XML的vCard格式的最后DTD可能會在下面的URL中找到:
http://www.vcard-xml.org/
?
? 例子1(對vCard的客戶端請求):
<iq type="get">
<vCard xmlns="vcard-temp"/>
</iq>
? 例子2(客戶端收到vCard數據):
<iq type="result">
<vCard version="3.0" xmlns="vcard-temp">
vCard data goes here
</vCard>
</iq>
? 例子3(客戶端向服務端發送vCard):
<iq type="set">
<vCard version="3.0">
vCard data goes here
</vCard>
</iq>
7. 使用用例
? 這一部分提供一些在Jabber協議上略有不同的觀點,通過用例來闡述。下面每一個例子都展示一個Jabber用戶完成一個完整的任務的消息流程,該流程包括接收和發送,如注冊到一臺服務器,登陸,改變當前狀態,或者發送一條消息。如果時間允許,我將把這部分引申的更遠。
7.1. Jabber用戶注冊
? 本用例同時邪顯示Jabber用戶向服務器開啟一個socket的連接,以及服務器的響應(如:<stream:stream>標簽)。
1. ? Jabber用戶通過開啟一個從客戶端到服務器端的XML流,來申請一個在服務器上的socket連接。
SEND: <stream:stream
to=’capulet.com’
xmlns=’jabber:client’
xmlns:stream=’http://etherx.jabber.org/streams’>
2. ? 服務器通過開啟一個從服務器到客戶端的XML流進行回復。
RECV: <stream:stream
from=’capulet.com’
id=’180763465’
xmlns=’jabber:client’
xmlns:stream=’http://etherx.jabber.org/streams’>
3. ? Jabber用戶提供一個需要注冊一個帳號(理論上,這需要一個不同的順序:首先詢問服務器需要什么信息,然后服務器器告知客戶端需要什么樣的信息;但在實際中,假定需要的信息是:用戶名,資源,密碼)的信息。
SEND: ? <iq id=’1’ type=’set’>
? ? ? <query xmlns=’jabber:iq:register’>
? ? ? ? ? <username>Juliet</username>
? ? ? ? ? <resource>balcony</resource>
? ? ? </query>
? ? </iq>
4. ? 服務器響應一個空的類型為”result”的iq元素,表示注冊已成功。
RECV: ? <iq id=’1’ type=’result’/>
7.2. Jabber用戶登陸
1. ? Jabber用戶詢問服務器,登陸所需要提供的信息。
SEND: <iq id=’2’ type=’get’>
? ? ? <query xmlns=’jabber:iq:auth’>
? ? ? ? <username>Juliet</username>
? ? ? </query>
? ? </iq>
2. ? 服務器提示Jabber用戶登陸所需要的信息。
RECV: <iq id=’2’ type=’result’>
? ? ? <query xmlns=’jabber:iq:auth’>
? ? ? ? <username>Juliet</username>
? ? ? ? <password/>
? ? ? ? <digest/>
? ? ? ? <sequence>500<sequence/>
? ? ? ? <token>3B905BFD</token>
? ? ? ? <resource/>
? ? ? </query>
? ? </iq>
3. ? Jabber用戶提供所需的信息——在本例中,是一個<hash/>元素,它是對信息進行一個零度知識認證的一個哈希。(詳情請見http://docs.jabber.org/draft-proto/html/zerok.html)。
SEND: <iq id=’3’ type=’set’>
? ? ? <query xmlns=’jabber:iq:auth’>
? ? ? ? <username>Juliet</username>
? ? ? ? <resource>balcony</resource>
? ? ? ? ? ? ? ? <hash>77d7eacde5e56b9622d0a075cb88361b110f
b9d7</hash>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
4. ? 服務器響應一個空的類型為”result”的iq元素,表明登陸成功。
RECV: <iq id=’3’ type=’result’/>
5. ? Jabber用戶發送當前狀態給服務器,表明其在線。
SEND: <presence>
? ? ? <status>Online</status>
? ? </presence>
7.3. Jabber用戶增加一個聯系人
1. ? Jabber客戶端在花名冊上增加一個聯系人(只是預備的操作)。
SEND: <iq type=’set’>
? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? <item jid=’romeo@montague.net’
Name=’remeo’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
2. ? Jabber用戶發送一個對該聯系人的訂閱請求。
SEND: <presence to’remeo@montague.net’ type=’subscribe’>
? ? ? <status>Wherefore are thou?</status>
? ? </presence>
3. ? 服務器發送一個花名單推送給用戶一個新條目和一個類型為”none”的訂閱(早已有了該訂閱)。
RECV: <iq type=’set’>
? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? <item jid=’romeo@montague.net’
name=’romeo’
subscription=’none’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
4. ? 服務器發送一個類型為”result”的iq包,表示花名冊推送成功(讓人有點疑惑的是,這個包是從Jabber用戶發送到Jabber用戶的!)
RECV: <iq
from=’juliet@capulet.com/balcony’
to=’julie@capulet.com/balcony’
type=’result’>
5. ? 服務器發送另一個花名單推送,這次是ask=’subscribe’屬性,表示訂閱的狀態未定。
RECV: <iq type=’set’>
? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? <item
ask=’subscribe’
jid=’romeo@montague.net’
name=’romeo’
subscription=’none’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
6. ? Romeo對訂閱請求的下一個響應會是什么呢?現在我們假定訂閱以Romeo接受訂閱請求為“結束”的。
RECV: <presence
from=’romeo@montague.net’
to=’juliet@capulet.com’
type=’subscribed’/>
7. ? 服務器再次發送一個花名單推送給客戶端,這次subscription=’to’,表示訂閱請求被接受了(Juliet現在可以訂閱到Romeo的當前狀態了)。
RECV: <iq type=’set’>
? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? <item
jid=’romeo@montague.net’
name=’romeo’
subscription=’to’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
7.4. Jabber用戶獲得花名冊
? ? ? SEND: <iq type=’get’>
? ? ? ? ? ? ? <query xmlns=’jabber:iq:roster’/>
? ? ? ? ? ? </iq>
RECV:<iq from=’juliet@capulet.com/balcony’ type=’result’> ?
? ? ? ? ? ? ? <query xmlns=’jabber:iq:roster’>
? ? ? ? ? ? ? ? <item
jid=’romeo@montague.net’
name=’romeo’
subscription=’both’/>
? ? ? ? ? ? ? </query>
? ? ? ? ? ? </iq>
7.5. Jabber用戶發送一條消息
? ? ? SEND: <message to’romeo@montague.net’>
? ? ? ? ? ? ? <body>Wherefore are thou?</body>
? ? ? ? ? ? </message>
? 注意:服務器會根據Jabber用戶的會話信息加上一個源地址,這樣接收者收到消息時,消息中已經包含了源地址。
7.6. Jabber用戶改變當前狀態
? ? SEND: <presence>
? ? ? ? ? ? <status>stepped away…</status>
? ? ? ? ? ? <show>away</show>
? ? ? ? </presence>
7.7. Jabber用戶登出
? 登出時很容易的,只需要關閉<stream>……
? ? SEND: </stream:stream>
? ? RECV: </stream:stream>
8. 參考文獻
? 本協議參考以下文獻
l ? ? ? Jabber開發指南(http://docs.jabber.org/jpg/)
l ? ? ? Jabber協議――標準(http://docs.jabber.org/proto/)
l ? ? ? Jabber協議――草案(http://docs.jabber.org/draft-proto/)
l ? ? ? Romeo and Juliet
(http://tech-two.mit.edu/Shakespeare/Tragedy/romoandjuliet/full.html)
9. 結束語
? 本文檔提供了一個關于Jabber的XML協議的一個詳細的怪數。如果你對本文檔有任何問題,請通過email或Jabber的方式自由地與作者聯系(Peter Saint-Andre),他的帳號時stpeter@jabber.org。
10. 版權信息
This document is copyright 2001 by Peter Saint-Andre.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (http://www.gnu.org/copyleft/fdl.html),
Version 1.1 or any later version published by the Free Software Foundation, with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You may obtain a
copy of the GNU Free Documentation License from the Free Software Foundation by
visiting http://www.fsf.org/ or by writing to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA
附錄 A 標準錯誤代碼
? 下面是Jabber中錯誤代碼的一些簡要描述。Jabber服務器在碰到不同的錯誤條件下生成這些錯誤代碼。一般Jabber錯誤代碼以HTTP規格的RFC 2616(http://www.ietf.org/rfc/rfc2616.txt)為基礎。但Jabber沒有使用所有的HTTP的錯誤代碼,并且Jabber錯誤代碼與HTTP錯誤代碼相對應時,通常只有Jabber自己的含義。注意本附錄只包含Jabber服務器生成的錯誤代碼,而不包括服務器端組件如網關發到外部消息系統。
錯誤代碼
描述
注意
302
重定向
盡管HTTP規定中包含八種不同代碼來表示重定向,Jabber只用了其中一個(用來代替所有的重定向錯誤)。不過Jabber代碼302是為以后的功能預留的,目前還沒有用到
400
壞請求
Jabber代碼400用來通知Jabber客戶端,一個請求因為其糟糕的語法不能被識別。例如,當一個Jabber客戶端發送一個的訂閱請求給它自己活發送一條沒有包含“to”屬性的消息,Jabber代碼400就會產生。
401
未授權的
Jabber代碼401用來通知Jabber客戶端它們提供的是錯誤的認證信息,如,在登陸一個Jabber服務器時使用一個錯誤的密碼,或未知的用戶名。
402
所需的費用
Jabber代碼402為未來使用進行保留,目前還不用到。
403
禁止
Jabber代碼403被Jabber服務器用來通知Jabber客戶端該客戶端的請求可以識別,但服務器拒絕執行。目前只用在注冊過程中的密碼存儲失敗。
404
沒有找到
Jabber代碼404用來表明Jabber服務器找不到任何與JabberID匹配的內容,該JabberID是一個Jabber客戶端發送消息的目的地。如,一個用戶打算向一個不存在的JabberID發送一條消息。如果接受者的Jabber服務器無法到達,將發送一個來自500級數的錯誤代碼。
405
不允許的
Jabber代碼405用在不允許操作被’from’地址標識的JabberID。例如,它可能產生在,一個非管理員用戶試圖在服務器上發送一條管理員級別的消息,或者一個用戶試圖發送一臺Jabber服務器的時間或版本,或者發送一個不同的JabberID的vCard。
406
不被接受的
Jabber代碼406用于服務器因為某些理由不接受一個包。例如,這個可能發生在,一個Jabber客戶端試圖使用jabber:iq:private在服務器上存儲信息,但當前的用于存儲的名字空間用”jabber:”開頭(在Jabber里是一個被存的XML開頭)。另一種可能產生406錯誤的情況是當一個Jabber客戶端試圖用一個空密碼注冊到一臺Jabber服務器上。
407
必須注冊
Jabber代碼407當前不被使用
408
注冊超時
當一個Jabber客戶端不能在服務器準備好的時間內發起一個請求時,Jabber服務器生成Jabber代碼408。這個代碼當前只用于Jabber會話管理器使用的零度認證模式中。
409
沖突
略
500
服務器內部錯誤
當一臺Jabber服務器遇到一種預期外的條件,該條件阻止服務器處理來自Jabber客戶端的包,這是將用到Jabber代碼500。現在,唯一會引發500錯誤代碼的時間是當一個Jabber客戶端試圖通過服務器認證,而該認證因為某些原因沒有被處理(如無法保存密碼)。
501
不可執行
當服務器不支持Jabber客戶端請求的功能,使用Jabber代碼501。例如,該代碼只當Jabber客戶端發送一個認證請求,而該認證請求不包含服務器配置中定義的任何一種認證方式時,服務器發送Jabber代碼501。這個代碼還被用于,當一個Jabber客戶端試圖注冊一個不允許注冊的服務器。
502
遠程服務器錯誤
當因為無法到達遠程服務器導致轉發一個包失敗時,使用Jabber代碼502。該代碼發送的特殊例子包括一個遠程服務器的連接的失敗,無法獲取遠程服務器的主機名,以及遠程服務器錯誤導致的外部時間過期。
503
服務無法獲得
當一個Jabber客戶端請求一個服務,而Jabber服務器通常由于一些臨時原因無法提供該服務時,使用Jabber代碼503。例如,一個Jabber客戶端試圖發送一條消息給另一個用戶,該用戶不在線,但它的服務器不提供離線存儲服務,服務器將返回一個503錯誤代碼給發送消息的JabberID。當為vcard-temp和jabber:iq:private名字空間設置信息時,出現通過xdb進行數據存儲的寫入錯誤,也使用該代碼。
504
遠程服務器超時
Jabber代碼504用于下列情況:試圖連接一臺服務器發生超時,錯誤的服務器名。
510
連接失敗
Jabber代碼510目前還沒有使用。
源文:http://www.blogjava.net/codefans/articles/20022.html