前端學(xué)習(xí):前后端數(shù)據(jù)通信之HTTP與WebSocket?

做可視化,如大屏,往往需要數(shù)據(jù)實(shí)時(shí)更新,那么怎么實(shí)現(xiàn)呢?

  • 下邊是簡單的思路:
    1. ajax短輪詢:每隔一段時(shí)間向服務(wù)端發(fā)送HTTP請求,服務(wù)器接收到請求后返回最新的數(shù)據(jù)!
    2. ajax長輪詢:與短輪詢類似,每隔一段時(shí)間向服務(wù)端發(fā)送HTTP請求,服務(wù)器接收到請求后,如果沒有更新的數(shù)據(jù),則阻塞程序,等到有數(shù)據(jù)更新時(shí)返回最新的數(shù)據(jù)!
    3. websocket:全雙工(雙向同時(shí)收發(fā)消息)通信,服務(wù)端有數(shù)據(jù)更新時(shí)可以主動推送到客戶端。

上邊說的只是簡單的實(shí)現(xiàn)方案,至于孰優(yōu)孰劣要從其各自背后的工作原理說起。說簡單點(diǎn),就是弄明白HTTP、WebSocket與服務(wù)器數(shù)據(jù)進(jìn)行通信過程的差異!

HTTP

之前的HTTP篇 講過,HTTP是無狀態(tài)的,為什么呢?因?yàn)镠TTP向服務(wù)器請求數(shù)據(jù)時(shí),先要通過TCP與服務(wù)器建立連接(三次握手),發(fā)送請求,服務(wù)器解析請求并返回相應(yīng)數(shù)據(jù),連接關(guān)閉(清除身份驗(yàn)證信息),完成一次請求過程。下次請求重新建立連接,重新驗(yàn)證身份。這樣一來,ajax輪詢的方式,需要不停的發(fā)送請求,每次都要重新握手,效率比較低下。
另外,HTTP請求是被動的,即客戶端發(fā)送request,服務(wù)端才會返回response。

WebSocket

2008年誕生的websocket,如今已被各大瀏覽器支持,與HTTP大致屬于求同存異的關(guān)系吧!WebSocket在向服務(wù)端請求數(shù)據(jù)是也是需要與服務(wù)端建立連接的(而且是借助HTTP建立連接的方式實(shí)現(xiàn)的,只不過在建立連接后通過‘Upgrade: websocket’的請求頭設(shè)置,將協(xié)議由HTTP轉(zhuǎn)換為websocket,之后的數(shù)據(jù)通信便于HTTP再無關(guān)系),只不過成功建立連接后,在數(shù)據(jù)相應(yīng)之后沒有立即關(guān)閉(長連接),而是以阻塞的形式繼續(xù)等待請求(因?yàn)閰f(xié)議變成了websocket),之后所有數(shù)據(jù)通信均由該連接完成。而且該連接是全雙工的,支持客戶端和服務(wù)端同時(shí)收發(fā)消息!


比較

通過上面的簡單介紹,相信你對HTTP與WebSocket在數(shù)據(jù)通信方面已經(jīng)有了一些認(rèn)識,以及對數(shù)據(jù)實(shí)時(shí)更新問題解決的優(yōu)劣也有了判斷。

  • ajax輪詢:需要重復(fù)建立連接,資源消耗大,效率低下;被動更新數(shù)據(jù)。
  • websocket:一次連接,終身受益;主被動兼顧!

實(shí)現(xiàn)

參考MDN-Git(JavaScript實(shí)現(xiàn)樣例),貼出主要代碼:

  • client.js
function connect() {
  // 以ws(s)開頭的URL
  var serverUrl = "ws://" + window.location.hostname + ":6502";
  // 創(chuàng)建連接
  connection = new WebSocket(serverUrl);
  connection.onopen = function(evt) {
    // 成功建立連接
  };

  connection.onmessage = function(evt) {
  // 從服務(wù)端接受到的消息
    var msg = JSON.parse(evt.data);
  //通過判斷消息type,執(zhí)行相關(guān)操作
    switch(msg.type) {
      case "id":
        // ...
        break;
      case "username":
        // ...
        break;
      case "message":
        // ...
        break;    
    }
}
  • server.js
var http = require("http");
var url = require("url");
var fs = require("fs");
var WebSocketServer = require("websocket").server;

var connectionArray = [];
var nextID = Date.now();
var appendToMakeUnique = 1;
const dirname = "./websocket-chat";

var server = http.createServer(function(request, response) {
  console.log(new Date() + " Received request for " + request.url);
  if (request.url === "/") {
    //設(shè)置編碼
    response.setHeader("Content-Type", "text/html;charset=utf-8");
    fs.createReadStream(dirname + "/index.html").pipe(response);
  } else {
    if (fs.existsSync(`.${request.url}`)) {      
      fs.createReadStream(`.${request.url}`).pipe(response);
    } else {
      response.statusCode = 404;
      response.end();
    }
  }
});
// 發(fā)布服務(wù),監(jiān)聽端口6502
server.listen(6502, function() {
  console.log(new Date() + " Server is listening on port 6502");
});

// Create the WebSocket server
var wsServer = new WebSocketServer({
  httpServer: server,
  autoAcceptConnections: true // You should use false here!
});

wsServer.on("connect", function(connection) {
   // ...

  // Handle the "message" event received over WebSocket. This
  // is a message sent by a client, and may be text to share with
  // other users or a command to the server.

  connection.on("message", function(message) {
    if (message.type === "utf8") {
      // Process messages

      var sendToClients = true;
      msg = JSON.parse(message.utf8Data);
      var connect = getConnectionForID(msg.id);

      switch (msg.type) {
        case "message":
          // ...
          break;
        case "username":
         // ...
          break;
      }      
  });

  // Handle the WebSocket "close" event; this means a user has logged off
  // or has been disconnected.
  connection.on("close", function(connection) {
   // ...
});

參考

時(shí)間和篇幅有限,不能完全解釋清楚,感興趣的可以討論或者參看參考列出的內(nèi)容


如果您感覺有所幫助,或者有問題需要交流,歡迎留言評論,非常感謝!
前端菜鳥,還請多多關(guān)照!


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • WebSocket簡介 談到Web實(shí)時(shí)推送,就不得不說WebSocket。在WebSocket出現(xiàn)之前,很多網(wǎng)站為...
    吧啦啦小湯圓閱讀 8,331評論 15 75
  • 上一篇談到了記憶。 這章說說,記憶的應(yīng)用。當(dāng)學(xué)生們在讀了《心理學(xué)與生活》這一章的內(nèi)容后,詢問最多的問題是:“我怎么...
    折疊人生閱讀 843評論 0 1
  • 半杯薄酒難入喉, 一襲青絲為誰留? 夢醒方知卿是客, 唯醉方可解心愁。 ——墨如初見
    墨如初見ainiya閱讀 384評論 3 7
  • 你知道“范雨素”嗎? 如果你是個(gè)關(guān)心時(shí)下熱點(diǎn)又對文學(xué)有點(diǎn)偏好的人,這幾天一定見過這個(gè)名字。 一篇題為《我是范雨素》...
    飛飛_魚閱讀 695評論 1 3

友情鏈接更多精彩內(nèi)容