基於XMPP的即時通信系統的建立 — XMPP IQ詳解

来源:http://www.cnblogs.com/lurenq/archive/2017/06/16/7026448.html
-Advertisement-
Play Games

XMPP詳解 XMPP(eXtensible Messaging and Presence Protocol,可擴展消息處理和現場協議)是一種在兩個地點間傳遞小型結構化數據的協議。在此基礎上,XMPP協議已經被用來構建大規模即時通信系統、游戲平臺、協作空間及語音和視頻會議系統。 XMPP由幾個小的構 ...


XMPP詳解

XMPP(eXtensible Messaging and Presence Protocol,可擴展消息處理和現場協議)是一種在兩個地點間傳遞小型結構化數據的協議。在此基礎上,XMPP協議已經被用來構建大規模即時通信系統、游戲平臺、協作空間及語音和視頻會議系統。

XMPP由幾個小的構造塊組成,併在此基礎上擴展出了更多的構造塊。XMPP中有眾多系統:發佈-訂閱服務、多人聊天、表單檢索與處理、服務發現、實時數據傳輸、隱私處理及遠程過程調用等。

大多數社交媒體(Facebook及Twitter)也採用了XMPP協議。

什麼是XMPP

與其他協議一樣,XMPP定義了在兩個或者更多通信實體間傳遞數據所採用的格式。對於XMPP,實體通常是指客戶端伺服器,但是其也允許客戶端與客戶端或伺服器端與伺服器端的通信。

在XMPP上交換的是XML數據,採用這種格式,使XMPP協議獲得了極大的可擴展性,因為使用XML可以方便的新增功能並保證前後向相容。使用XML較二進位協議占用更大的帶寬,但獲得的優勢是具有了幾乎無限的可擴展性。

用戶可以向XMPP Standards Foundation註冊協議擴展。

在XMPP中,XML數據被組織為了一對流,每個流分別對應通信的一個方向。每個XML流均由一個開始元素、後跟XMPP節和其他頂級元素,然後是一個結束元素組成。每個XMPP節(可帶有子元素及屬性)均是該流的一級子元素。在XMPP連接末尾,這兩個流形成了一對有效的XMPP文檔。

XMPP節構成了該協議的核心部分,而XMPP應用程式則關註如何發送和響應各種類型的節。節可能包含網路上其他實體的信息、類似於電子郵件的個人消息或為電腦處理而設計的結構化數據。

<message to=’[email protected]’ from=’[email protected]/dance’ type=’chat’>

         <body>what think you of books</body>

</message>

在一個典型的XMPP會話中,一個上述的節將會從darcy的XMPP客戶端發送到她的XMPP伺服器,她的伺服器將會註意到該節的目的地是某個遠程伺服器上的一個實體,因此與該遠程伺服器先建立XMPP連接,並將消息轉發該處。

這種通信網路與電子郵件類似,但與電子郵件伺服器不同的是,XMPP間的伺服器可以直接通信,而不需要藉助中間伺服器。

這種直接通信避免了垃圾信息的干擾,且還支持通過TLS(Transport Layer Security,傳輸層安全)來加密通信並通過SASL(Simple Authentication and Security Layers,簡單身份驗證與安全層)實現身份驗證機制。

XMPP使用傳遞短小信息來設計的,而非針對大型數據塊,但XMPP能夠用來協商並建立可在端點間傳遞大型數據塊的帶內或者帶外傳輸。

XMPP歷史

最初各大公司發佈的ICQ均基於其公司運營的專有協議和網路(ICQ,Yahoo Pager)。

開發人員企圖互通這些IM的努力由於協議的閉源特性失敗了。

1991年1月Jeremie Miller發佈了Jabber項目,Jabber是基於XML的去中心化的即時通信協議,同時也是一個叫jabberd的伺服器實現。

2000年5月,Jabber的核心協議穩定,jabberd也正式發佈了。

2001年,JSF(Jabber Software Foundation,Jabber軟體基金會)成立,並開始圍繞jabber協議做規範性工作。

2002年12月,JSF向IETF提交了核心規範,併成立了一個IETF小組。

2004年10月,這個標準化進程產生了Jabber協議的改進版,改名為XMPP,其文檔成為RFC標準,編號分別為3920、3921、3922和3923。

最初開發人員向JSF提交的擴展稱為JEP(Jabber Extension Proposal,Jabber擴展提議)。最終隨著Jabber過度到XMPP,JSF更名為XSF(XMPP Standard Foundation,XMPP標準基金會)和XEP(XMPP Extension Proposal,XMPP擴展提議)。

2005年XMPP技術開始大規模部署,例如Google Talk。

先進有大約300個XEP,並有數十種客戶端和服務端實現,開源及商用均有,實際上,任何編程語言都可以找到這樣一個庫來加速XMPP開發進程。

XMPP網路

任何XMPP網路都是由若幹角色組成,可以分為伺服器端、客戶端、組件和伺服器插件。

XMPP網路與WWW網路及EMAIL網路不同,XMPP伺服器之間定址只會跳一次,而EMAIL協議則會有多個中轉伺服器,XMPP保存完整的列表。

 

伺服器

XMPP伺服器是任何XMPP網路的通信系統,伺服器的任務就是為XMPP節提供路由。無論這些節是從內部的一個用戶發往另外一個用戶還是本地用戶發送給伺服器。

一組能夠相互通信的XMPP伺服器構成了XMPP網路。

XMPP伺服器總是允許用戶連接到自己,但是也可以編寫直接使用伺服器-伺服器協議的應用和程式,來減輕路由消耗。

Ejabberd、Openfire和Tigase是三種能夠運行在Windows,Mac OS X和Linux的開源伺服器。

M-Link和Jabber XCP是商用產品。

客戶端

大多數XMPP實體均是客戶端,通過客戶端-伺服器協議連接到XMPP伺服器。

客戶端必須向某個地方的XMPP伺服器進行身份驗證。伺服器會將該客戶端發送的所有節路由到合適的目的地。

伺服器還負責管理客戶端會話的其他幾個方面,包括花名冊及裸地址。

組件

不僅僅是客戶端能夠連接到XMPP伺服器,大多數伺服器還支持外部伺服器組件。這些組件通過添加某種新服務來增強伺服器的行為。這些組件在伺服器內有各自的身份和地址,但運行在外部並通過組件協議通信。

組件協議(XEP-0114)可以讓開發人員以一種伺服器不可知的方式創建伺服器擴展,例如多人聊天服務。

組件也需要向XMPP伺服器進行身份驗證,但要較客戶端的完全SASL驗證簡單,例如口令。

每個組件編程伺服器內部一個可單獨定址的實體,在外界看類似於一個子伺服器。除了基本節之外,XMPP伺服器不會代替已連接組件來管理其他節的路由。

伺服器還允許組件在內部自行路由或管理節,因而更為靈活。

插件

許多XMPP伺服器還支持使用插件進行擴展,但插件深入到伺服器內部,有較高的效率以及最低的通用性。

插件一般是綁定特定類型的伺服器的。

XMPP定址

XMPP網路上的每個實體都有一個或多個地址(稱為JID,jabber identifier)。通常類似於:

[email protected][email protected]就是兩個JID。

JID由三個部分組成,節點、域和資源,域是必須的,其他兩個部分是可選的。

域是實體(伺服器、組件或插件)可解析的DNS名稱。僅由域組成的JID是有效地址,表示伺服器地址。指向域的節將由伺服器自身處理,並可能被路由到某個組件或插件。

本地部分通常用來識別域中的一個特定用戶,位於@前。本地部分也可以用來識別其他對象,如某個聊天室。

JID的資源部分通常會標識一個特定客戶端的XMPP連接。對於XMPP客戶端而言,每個連接均被指派一個資源。[email protected]想要連接他的書法和圖書館則可以通過

[email protected]/study[email protected]/library來定址,這樣避免了用戶在打開多個鏈接時消息無法找到正確的處理器。主要註意的是,資源部分是區分大小寫的。

JID劃分為兩種類型:

  • Ÿ   裸JID

完整JID去除資源部分的地址,客戶端的裸JID有些特殊,這是因為伺服器自己將處理髮往客戶端的裸JID節。裸JID可以視為定址用戶的賬戶,而不是客戶端。

  • Ÿ   完整JID

最為具體的地址

XMPP節

核心XMPP工具集由三個基本節組成,分別為<presence>、<message>和<iq>

XMPP流由兩份XML文檔組成,通信的每個方向均有一個文檔,這些文檔有一個根元素<stream:stream>,<stream:stream>的子元素由可路由的節以及與流相關的頂級子元素構成。

複製代碼
<stream:stream>
         <iq type=’get’>
             <query xmlns=’jabber:iq:roster’ />  //請求自己的花名冊
         </iq>
         <presence/>  //通知伺服器她已線上並可以訪問
         <message to=’[email protected]’ from=’[email protected]/ballroom’ type=’chat’>
             <body>
                   I cannot talk of books in a ball-room; my head is always full of something else.
             </body> //發送消息
         </message>
         <presence type=’unavailable’> // 聲明自己不可訪問並關閉
</stream:stream>
複製代碼

通用屬性

from/to/type/id

from的屬性並非由客戶端提供,而是服務端進行的標記。

presence節

presence提供網路實體的可訪問性。用戶發出presence節,表明自己上線,這樣可以會有更大的概率與別人通信(人們更願意與線上的人交流),但是我們也不用擔心任何人都可以看到自己的線上狀態,除非我們訂閱了該用戶的狀態,訂閱之後,用戶的狀態信息會自動發送到訂閱者處。

實際上,XMPP的presence節是一個簡單的專用的發佈-訂閱方法。

在IM中,presence體現在花名冊(roster)中,花名冊保存有JID列表以及用戶與這些JID的訂閱關係,一旦上線,用戶發送presence節,剩下的就由伺服器處理了(通知自己線上,以及獲取聯繫人的狀態信息)

message節

用於從一個實體向另外一個實體發送消息,並可以傳輸任何類型的結構化信息,不保證傳輸可靠性

message是一個非常基礎的推模型,message通常用於IM,groupchat,警告和通知等。

message的type有如下幾種:

  • normal

    類似於email,發出後不等待回應

  • chat

    用於兩個實體間的實時通信

  • groupchat

    多用戶聊天室中使用

  • headline

    用於發送警告或通知

  • error

發送錯誤信息

<message [email protected]/foo [email protected] type="chat">
  <body>Who are you?</body>
  <subject>Query</subject>
</message>

除了type之外,典型的message節中還包含from、to或者id屬性(用於目的追蹤)。

to中的JID為消息的接受者,from是發送者的JID,但是from屬性並非由客戶端提供,而是發送者的服務端提供的,以避免地址模仿。

message節中也可以包含未在XMPP協議中定義的負載,可以用於擴展。

IQ節

表示Info/Query,為XMPP通信提供請求及響應機制,類似於GET/POST/PUT方法。

IQ只能包含一個payload,並且定義了需要由伺服器處理的請求或者動作。相對於message來說,IQ具有更好的可靠性,因其要求收到回應。

IQ中包含有id屬性,用於識別伺服器發回的響應。

  • get

    用於請求信息,類似於HTTP Get

  • set

    提供信息或請求,類似於HTTP POST/PUT

  • result

    響應請求,類似於HTTP 200

  • error

    錯誤信息

例子

  • 發送獲取花名冊請求
<iq [email protected]/pda id="rr82a1z7" [email protected] type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
  • 伺服器返回花名冊
複製代碼
<iq [email protected] id="rr82a1z7" [email protected]/pda type="result">
    <query xmlns="jabber:iq:roster">
        <item jid="[email protected]"/>
        <item jid="[email protected]"/>
        <item jid="[email protected]"/>
        <item jid="[email protected]"/>
    </query>
</iq>            
複製代碼
  • 用戶新增一個聯繫人
<iq [email protected]/pda id="ru761vd7" [email protected] type="set">
    <query xmlns="jabber:iq:roster">
        <item jid="[email protected]"/>
    </query>
</iq>
  • 伺服器響應
<iq [email protected] id="ru761vd7" [email protected]/pda type="result"/>

error節

具有明確的結構,通常包含原節內容,通用錯誤信息以及應用程式特有的錯誤條件和信息(可選)

可擴展

XMPP協議是基於XML的協議,因此其天生提供了很好的可擴展性。我們可以用XMPP傳遞各種信息,包括鏈接、位置信息,Web Service等。

連接生命周期

發送XMPP節通常需要建立一個經過身份驗證的XMPP會話,包括連接、流的建立、身份驗證以及斷開連接。

連接

在發送任何節之前,需要建立XMPP流,在XMPP流存在之前,必須建立通往XMPP伺服器的連接。

當XMPP客戶端或者伺服器連接到另外一個XMPP伺服器時,首先要查詢SRV記錄,該記錄保存有特定域的伺服器列表。查詢應答中可以包含多條SRV記錄,這樣就可以在多個伺服器中建立負載均衡連接。

如果沒有找到合適的SRV記錄,那麼程式將試圖直接連接到指定域。

流的建立

Ÿ   一旦建立通過給定XMPP伺服器的連接,XMPP流就啟動了

Ÿ   向伺服器發送<stream:stream>,就可以打開XMPP流,伺服器發送響應流的起始標記<stream:stream>進行響應

建立XMPP流之後就可以來回發送各種元素

Ÿ   伺服器發送<stream:feature>元素,列舉XMPP流中支持所有功能,大多數與可用的加密和身份驗證選型有關

身份驗證

XMPP允許進行TLS(Transport Layer Security,傳輸層安全)加密,而且大多數客戶端預設使用該功能。

一旦伺服器通告TLS支持後,客戶端就會啟動TLS連接並將當前套接字升級為加密套接字而不斷開連接。一旦TLS加密確立,就會創建一對新的XMPP流。

XMPP中的身份驗證使用SASL(Simple Authentication and Security Layers,簡單身份驗證與安全層)協議並支持多種身份驗證機制(取決於伺服器)。

一旦完成身份驗證,客戶端必須為連接綁定一個資源並啟動一個會話,通過<bind>和<session>元素髮送。

當兩台伺服器相互連接時,身份驗證步驟稍稍不同。

連接斷開

當用戶結束XMPP會話後,他們終止會話並斷開連接,最優雅的方式是首先發送無效出席信息,然後關閉<stream:stream>元素。

<presence type=’unavailable’>
</steam:stream>

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 緊接著上面寫的... 給div加一個邊框,border:1px solid black window.onload = function(){ var div = document.getElementById('div1'); div.onclick = function(){ setInterv ...
  • 微信的圖像有3種JSSDK的API,可以做一些簡單的需求,本節講解一個讓用戶在手機中選擇照片然後分享的項目。 ...
  • 用CSS和jQuery來實現它,儘量看起來和原效果一樣。 最終效果圖 最終效果圖 本教程里,我將使用CSS,HTML和jQuery來創建一個近似Apple TV視差效果,如果你正在閱讀,我假設你對上述三種技術都有基本的瞭解。 廢話不多說,開始第一部分。 HTML頁面 我們的頁面結構像下麵這樣: 首先 ...
  • 1.index.Android.js 2.在項目的 index.android.js同一目錄下 創建json文件 這樣方便圖片的訪問,資源圖片放在項目名稱\android\app\src\main\res\drawable 下麵 這裡的BadgeData.json 如下: 3.主要的文件 scrol ...
  • 我們在瀏覽淘寶京東等大型購物網頁時會經常出現許多圖片而圖片需要花費我們非常多的流量問題。 我們在寫網頁的時候怎麼解決這個問題呢?這時候就要用到我們圖片懶載入的問題,這樣不僅可以 解決流量問題,也提高了性能等等。 下麵我們就來看一下圖片的懶載入怎麼問題。 ...
  • 1.層級選擇器 後代選擇器 "父元素 後代元素" 比如:$("div p") 選取div元素下所有的p元素 子元素選擇器 "父元素 > 子元素" 比如:$("div>p") 選取div的子元素中的p元素 第一個向後兄弟元素 "元素名+兄弟元素" 比如:$("div+p") 選取div元素後的第一個p ...
  • 一.Javascript的含義 是一種解釋性的語言,主要給網頁添加各色各樣的動態功能,同時為用戶提供瀏覽效果。 二.JavaScript的主要特點 三.JavaScript的組成 四.JavaScript的三種引入方式 1.標簽內引入2.內部引入3.外部引入 五.javaScript語法的基本要求 ...
  • nodejs中文網,官網同步翻譯 http://nodejs.cn/api/ Webpack 中文手冊(社區同步翻譯) http://6.course.uprogrammer.cn/webpack2 doc cn/index.html ECMAScript6 中文教程 https://www.w3c ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...