XMPP學習及使用2

即時消息傳遞(IM)在臨時 Internet 用戶和業務用戶中都是一個受歡迎的應用程序。它不僅爲用戶提供了與他人進行實時通信的方法,還能夠得到他們的到場信息(在線、離開、離線,等等)。Jabber 是最早的開放 IM 協議之一,由 Jeremie Miller 開發並於 1998 年作爲一個非標準 IM 協議出現。由於 Jabber 是使用 XML 創建的可擴展協議,它很快就創建了其他可用作通用傳輸或面向消息的中間件(MoM)的應用程序。最終由 Jabber 產生了 XMPP,這是一個 IETF 工作組協議文檔形式的基於標準的協議:RFC 3920,“可擴展消息傳遞和到場協議(XMPP)”。

  XMPP 並不是惟一的通用消息傳遞協議。其他受歡迎的協議(如 XML-RPC 和 SOAP)能夠爲這個功能提供函數調用(如語義)。一些較新的方法,如具象狀態傳輸(ReST),使用 URL 指定位置、對象和方法,提供受控制的文件訪問。

 

XMPP 架構

  XMPP 與其他的應用層協議(如SMTP)有着相似之處。在這些架構中,具有惟一名稱的客戶機通過相關的服務器與另外一個具有惟一名稱的客戶機進行通信。每個客戶機執行客戶機的協議表單,而服務器在表單中提供路由功能。圖 1 說明了這個簡單的架構。在這個例子中,每個客戶機都是同一個域名(discovery.nasa.guv)的一部分。

圖 1. 由一個服務器和兩個客戶機組成的簡單的 XMPP 架構

 

  服務器還可以針對不同域之間(例如,在 discovery.nasa.guv 和 europa.nasa.guv 之間)的路由進行通信。此外,網關可用於在外部消息傳遞域和協議之間進行轉換。圖 2 中的示例顯示了一個 XMPP 網絡,網關通往一個短信服務(SMS)域和一個 SMTP 域。在這種情況下,網關大多數都是被用來在 IM 協議(例如,在 XMPP 和 Internet 中繼聊天(IRC))之間進行轉換。作爲一個可擴展的協議,XMPP 對於在不同的端點協議間提供統一連接性來說是一個理想的中樞協議。XMPP 網關允許終止一個給定的客戶端到服務器的會話,並且向目標端點協議發起一個新的會話(同時進行必要的協議轉換)。

圖 2. 包含了 XMPP 網關的更爲複雜的 XMPP 架構

 

XMPP 中的地址

XMPP 中的地址(即 Jabber ID[JID])與標準電子郵件地址相似,但有着幾個顯著的差別。JID 包含一個可選節點、一個域和一個可選資源:

[ node "@" ] domain [ "/" resource ]

 

最常見的用法就是定義一個 IM 用戶(類似電子郵件地址),比如 [email protected]。用戶能夠多次登錄 XMPP 服務器,而在這個例子中,資源能夠表示位置。例如,示例用戶可能有一個主終端([email protected]/terminal)JID 和另外一個來自 EVA pod([email protected]/eva_pod1)的 JID。因此,能夠找到某個特定位置,或離開此位置並找到用戶,不管用戶在哪個位置登錄。

XMPP 協議

XMPP 是一個相對簡單的協議,它通過 XML 消息出現在 TCP 套接字上。異步通信發生在 XML 流中,並帶有 XML 節(stanza)。XML 流 是封裝了兩個實體間的 XML 信息交換的容器。XML 流傳遞 XML 節,這些 XML 節是一些分散的信息單元。例如,在 XMPP 中使用 XML 節傳遞消息(IM 用戶間的文本)以及到場信息。爲說明這些概念,請看一個在兩個客戶端之間使用 XMPP 進行 IM 通信的簡單示例。

圖 3 演示了兩個實體之間的簡單會話。注意,至少有一個服務器會出現在會話中(在這個例子中,因爲兩個客戶端存在於同一個域中,所以準確地說,只有一個服務器)。在 圖 3 中,左邊的客戶端是發起實體(發起兩個實體間的 XMPP 通信)。XML 流使用 to 屬性來識別接收域(以及定義 XML 名稱空間)。右邊的接收客戶端 接收 XML 流並使用 XML 流響應(在這個例子中,使用 from 屬性)進行迴應。在這個階段,可以進行幾個不同的協商(如驗證和加密)。請忽略這部分討論(例外情況是當 IM 客戶端出現在不同的域中進行服務器到服務器通信)。(請查看 圖 3 的文字版本。)

圖 3. 示例(簡化的)XMPP 通信

圖 3 中的 XML 流的下一步是進行消息傳遞。這個通信在消息節中進行,並且包括了源和目標 XMPP 地址(from 和to)、使用的語言以及節正文中的消息。對方用其自己的消息進行響應,關鍵區別是源和目標 XMPP 地址。最後,發出流關閉消息(在連接的兩端進行)以關閉 XML 流。

任何一邊都可能返回一個錯誤,如下面所定義。在本例中,對方發送了一個無效的 XML 流和節。

<stream:error>
  <xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
<stream:error>

 

儘管這個示例展示了簡單的 IM 通信,但很容易就能瞭解消息節是如何轉換成 RPC 消息的,同時負載了來自對等協商的安全問題。您可以把函數註冊爲節點,以創建一個動態的 Web 服務框架,而不是對域中的用戶進行註冊。現在讓我們看一下如何創建一個在 XMPP 中通信的簡單應用程序。

使用 Ruby 的 XMPP 示例

選擇 XMPP 庫

XMPP 其他有趣方面的其中之一就是您可以在大量的庫中進行選擇,包括各種各樣的語言。這個示例使用了 Ruby 語言和 XMPP4R 庫。要獲取現有的各種庫的鏈接,請查看 參考資料

通過庫來演示 XMPP,探究用作技術字典的簡單 IM 代理的開發。使用這種方法,您通過一個標準的即時消息程序輸入一個詞時,IM 代理將返回它的定義。

本示例實現了可以通過 XMPP 連接到其他 IM 代理的 IM 代理,並且一旦連接成功,將解釋詞語的定義。清單 1 提供了簡單的 XMPP 代理。


清單 1. 用於文字定義的簡單 XMPP 代理

				
require 'xmpp4r/client'

# Create a *very* simple dictionary using a hash
hash = {}
hash['ruby'] = 'Greatest little object oriented scripting language'
hash['xmpp4r'] = 'Simple XMPP library for ruby'
hash['xmpp'] = 'Extensible Messaging and Presence Protocol'

# Connect to the server and authenticate
jid = Jabber::JID::new('[email protected]/Home')
cl = Jabber::Client::new(jid)
cl.connect
cl.auth('password')

# Indicate our presence to the server
cl.send Jabber::Presence::new

# Send a salutation to a given user that we're ready
salutation = Jabber::Message::new( '[email protected]', 'DictBot ready' )
salutation.set_type(:chat).set_id('1')
cl.send salutation 

# Add a message callback to respond to peer requests
cl.add_message_callback do |inmsg|

    # Lookup the word in the dictionary
    resp = hash[inmsg.body]
    if resp == nil
      resp = "don't know about " + inmsg.body
    end

    # Send the response
    outmsg = Jabber::Message::new( inmsg.from, resp )
    outmsg.set_type(:chat).set_id('1')
    cl.send outmsg

end

# Run
while 1
end

 

清單 1 首先創建了一個簡單的字典。爲此,您可以使用 Ruby 中的 hash 類,它允許您創建鍵值對(類似於數組),但是隨後可以輕鬆地通過鍵引用它們。接下來,使用 XMPP4R 庫連接到服務器。首先使用 Client 類創建一個 JID 和一個新的客戶端連接。要真正連接到 IM 服務器,請使用 connect 方法。一旦連接上了,您可以使用密碼來調用 auth 方法。現在,連接已經可以用來傳遞消息了。

下一步(可選)是表示您已經登錄了 IM 服務器。爲此,需要向服務器發送一個 presence 節。您還可以發送一個可選信息給對方,告訴對方您已在線了。這點可以通過創建一個消息節並使用對方地址和消息對它進行初始化來實現。消息初始化成功後,可以通過對 Client 類實例使用 send 方法來發送它。

要對發送給您的消息作出反應,請使用您的客戶端連接的 add_message_callback 方法。任何時候消息到達時,都將調用代碼塊來處理消息。傳入消息表示爲 inmsgMessage 實例)。首先要進行檢查,看看傳入消息 body 定義的詞是否在您的字典中。如果返回 nil,那麼表示沒有找到該詞,因此您需要提供一個默認的響應。使用傳入消息(inmsg.from)和響應字符串創建一個新的消息。初始化完成後,通過客戶端實例把新消息發送給發送方。

圖 4 顯示了應用程序的一次運行。本示例使用了受歡迎的 pidgin 通用聊天客戶端。pidgin 客戶端支持所有主要的聊天協議,並可以與許多現有的聊天網絡一起使用(甚至是同步進行)。圖 4 顯示了當 IM 代理連接到服務器並與定義用戶開始會話時創建的消息傳遞彈出窗口。


圖 4. 使用 IM 代理的示例 IM 會話
使用 IM 代理的示例 IM 會話的屏幕截圖 

這個應用程序原本非常簡單,但是 XMPP4R 爲其他的功能(如帳戶註冊、發現、文件遷移、多用戶聊天、發佈/訂閱,甚至 RPC)提供了許多類和方法。您可以在 參考資料 中找到一個 “可瀏覽的” 類 API,它爲查看所有的 XMPP4R 文件、類和方法提供了一個方便的方法。

 

XMPP 的應用

XMPP 爲網絡中的消息傳遞提供了一個通用框架。除了傳統的 IM 和到場數據分佈外,XMPP 還可以用於許多不同用途。

IM 的封閉式應用包括小組或多方消息傳遞,或開發多用戶聊天室。使用多方通信,可以實現與 Twitter 提供的微博客(micro-blogging)類似的功能。但是文本並不是惟一可以通過 XMPP 傳送的數據。其他的通信形式包括聲音、圖片和視頻數據。

如今出現了服務發現協議(比如 Bonjour 或 Service Location Protocol),但 XMPP 爲網絡中的服務發現以及服務與功能的宣傳提供了堅實的基礎。

在線遊戲大量地使用了 XMPP。XMPP 爲在線遊戲提供了一組關鍵的功能,包括驗證、到場信息、聊天,以及可擴展的遊戲狀態信息的接近實時的交流。

最後,XMPP 是新的雲計算時代的一個完美協議。雲計算和存儲系統依賴不同層次和形式的通信,不僅包括在系統間進行消息傳遞以中繼狀態,還包括較大對象(如存儲或虛擬機器)的遷移。通過結合身份驗證和傳輸中的數據保護,XMPP 可以應用在不同的層次,而且可以作爲一個理想的中間件協議。

在此請注意,大多數應用與人類通信沒有任何的關係,而是關係到機器通信(MMI 或機器到機器的通信)。當您發現用於 IM 的協議有着各種各樣的用途時,您會覺得這是非常有趣的事情。


多語言的 XMPP

XMPP 是作爲一組庫實現的,爲應用程序提供了 XMPP 能力。從 XMPP 支持衆多語言這點就能輕鬆判斷出,XMPP 是一種非常有用的協議。您將發現 XMPP 庫軟件支持傳統語言(如 C 和 C++)以及受歡迎的腳本語言(如 Ruby、Java™ 語言、Python、Perl 和 Tcl)。您還將發現 XMPP 庫支持其他一些語言,如 Erlang、C# 和 Lisp。因此,不管您在何種環境中,都有可能找到一種 XMPP 庫來訪問 XMPP。要獲得各種 XMPP 庫支持的語言列表,請查看 參考資料

 

結束語

不斷成長的 ReST

儘管 ReST 是一個架構模型而非實現方法,但它在一些領域中成長得很快。ReST 的用於遠程資源管理的簡單模型已經存放在了雲存儲中,在那裏,ReST 被用作存儲訪問和管理模型。

許多有用的技術常常以全新的方式使用,這些方式是技術創建者當初從未考慮過的。例如,HTTP 是服務於 Internet 上的 Web 頁面的事實標準協議,但它同時也用作針對 SOAP 和 XML-RPC 等其他協議(包括 ReST 之類的協議模型)的應用層傳輸。XMPP 是另外一個發掘出除了 IM 外的其他許多新應用的有用技術。您將如何把 XMPP 引用到您的解決方案中呢?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章