MQTT協議筆記之mqtt.io項目HTTP協議支持


前言

MQTT協議誕生之初,就未曾考慮通過HTTP傳輸。這也正常,網絡受限、不穩定網絡不太適合HTTP(2G/3G網絡大家使用WAP不也OK嘛)。在網絡較為充裕的桌面端而言,雖純文本對比二進制而言沒多大優勢,受制於歷史遺留和使用習慣,以及一大票傳統基礎設施方便控制事宜,傳統互聯網/企業型應用,HTTP協議都是默認最佳選擇,安全可控,人機友好。選擇HTTP也在情理之中。

雖桌面端日漸式微,但做統一的全平台化消息系統/消息中間件,也是趨勢。

MQTT OVER HTTP,為WEB環境提供HTTP通道協議支持,在統一平台化這樣的考量下,就顯得合情合理。 MQTT相比其它基於HTTP的交換協議而言(比如socket.io),流量節省,消息質量可控。

一句話,比它強大的,沒有它輕量。比它還輕的,沒有它可控。

總之,在資源受限環境下表現如此優異,那么桌面端會表現的更為優秀。

HTTP支持情況

二進制支持,針對瀏覽器端JavaScript而言,處理起來,如同在石器時代要處理工業時代一些通訊方式,非常吃力。支持Javascript二進制操作的瀏覽器現狀:

xhr2

來源於:http://caniuse.com/xhr2

這和支持Websocket的瀏覽器的基本重疊。

要想讓HTTP傳輸MQTT具體消息二進制,然后由瀏覽器javascript腳本進行解析,無法做到支持所有常見瀏覽器,需要考慮純文本方式的傳輸。

設計摘要

AJAX方式,支持跨域,支持所有主流平台,桌面+移動設備;所有瀏覽器,移動的,桌面的,包括IE6+。那么最理想方式就是JSONP,基於文本通信的Long-polling JSONP方式。

MQTT 協議關鍵交互點: 1. 連接獲取授權 1. 訂閱/退訂主題 1. 發布消息 1. 等待訂閱消息 1. 關閉連接

若支持HTTP方式完成以上功能/步驟,服務器端需要支持接收HTTP純文本內容請求,拼裝、轉換成Java對象,業務層面實現數據流轉、交換,直接插入到更具體業務中,這樣就很容易。雖類似於橋接,但減少了橋接的路徑(HTTP —》MQTT),減少資源占用,性能上有所保證。

HTTP 文本方式,和MQTT二進制之間需要某些規則的轉換,為了兼容,需要單獨定義接口傳輸接口,ChannelEntry,雙通道和單通道處理數據的方式不同,單通道的HTTP JSONP需要支持短暫緩存消息並等待客戶端的依次獲取。發布/接收訂閱消息時,TCP/Websocket利用雙通道對應Channel可直接發送。

HTTP通道已經預留出接口,便於支持其它類型的HTTP傳輸通道,比如需要在非瀏覽器環境中實現常規的long polling/Http Streaming,僅僅需要做到實現相應接口即可。

客戶端ID的生成方式,一般是由服務器端生成的SessionId決定。傳輸純文本方式比較結構化JSON結構比較合適。

JSONP只支持HTTP GET方式,這一點需要牢記。

傳輸接口定義

  1. 連接獲取授權 /jsonp/connect
  2. 訂閱主題 /jsonp/subscribe
  3. 等待訂閱消息 /jsonp/waiting
  4. 發布主題 /jsonp/publish
  5. 退訂主題 /jsonp/unsubscrible
  6. 關閉連接 /jsonp/disconnect

要求返回的消息類型都是JSON字符串形式,訂閱/發布的消息,一定要包含{id:10, msg:'具體消息內容'}類似json字符串。

簡單示范

一般傳輸的是文字內容,但具有結構化的,非json莫屬。無論是走TCP方式二進制流還是JSONP傳輸的內容體,json都是不錯的可結構化數據的選擇。

瀏覽器端jquery,支持jsonp請求,這里有一個簡單示范:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
<!DOCTYPE html>
< html>
< head>
< meta charset="UTF-8">
< title>jsonp example</title>
< script src="http://libs.baidu.com/jquery/1.5.0/jquery.js"></script>
<script type="text/javascript">
var clientId = "";
var urlPrefix = "http://127.0.0.1:8080/jsonp";
$(document).ready(function(){
doConnect();
});
 
function doConnect(){
jreq(urlPrefix + '/connect', '', function(data){
if(data.status){
log("connected!");
clientId = data.clientId;
doSub();
}else{
alert("failure !");
}
});
}
 
function doSub(){
jreq(urlPrefix + '/subscribe', 'topic=sub-msg/webclient1', function(data){
if(data.status){
log("subscribed!");
doWaiting();
}else{
log("bad!");
}
});
}
 
function doWaiting(){
jreq(urlPrefix + '/waiting', '', function(data){
log("Got Message : id = " + data.id + " msg = " + data.msg);
doWaiting();
});
}
 
function jreq(url, parameter, fn){
$.ajax({
url:url,
dataType:"jsonp",
jsonp:"jsonpcallback",
data: parameter,
timeout: 300000,
async:true,
success:function(data){
fn(data);
}
});
}
 
function log(val){
$("#log").html(val + "<br/>" + $("#log").html());
}
</script>
</ head>
< body>
< div id="log"></div>
</ body>
</ html>
view raw jsonp.html hosted with ❤ by  GitHub

 

填寫好地址,自動執行連接,訂閱,接收消息,一個最簡單的Demo表現了其流程。

小結

簡單實現jsonp形式的MQTT OVER HTTP,做到文本和二進制彼此之間交換數據。總之在純HTTP環境下使用MQTT協議,是一個不錯的選擇。

 原文 http://www.blogjava.net/yongboy/archive/2014/06/06/414474.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM