websocket學習和羣聊實現

WebSocket協議能夠實現先後端全雙工通訊,從而取代浪費資源的長輪詢。在此協議的基礎上,能夠實現先後端數據、多端數據,真正的 實時響應。在學習 WebSocket的過程當中,實現了一個簡化版羣聊,過程和代碼詳細記錄在這篇文章中。

本篇文章來自董沅鑫的我的網站,引用、轉載請指明出處javascript

查看更多知識,或者技術交流:請訪問godbmw.comcss

1 概述

1.1 WebSocket 是什麼?

  1. 創建在 TCP 協議之上的網絡通訊協議
  2. 全雙工通訊協議
  3. 沒有同源限制
  4. 能夠發送文本、二進制數據等

1.2 爲何須要 WebSocket?

瞭解計算機網絡協議的人,應該都知道:HTTP 協議是一種無狀態的、無鏈接的、單向的應用層協議。它採用了請求/響應模型。通訊請求只能由客戶端發起,服務端對請求作出應答處理。html

這種通訊模型有一個弊端:HTTP 協議沒法實現服務器主動向客戶端發起消息。java

所以,若是在客戶端想實時監聽服務器變化,必須使用 ajax 來進行輪詢,效率低,浪費資源。node

而 websocket 就可使得先後端進行全雙工通訊(兩方均可以向對方進行數據推送),是真正的平等對話jquery

2 WebSocket 客戶端

支持HTML5的瀏覽器支持 WebSocket 協議:git

var ws = new WebSocket(url); // 建立一個websocket對象

2.1 WebSocket 屬性

屬性 描述
ws.readyState 只讀屬性 readyState 表示鏈接狀態,能夠是如下值:0 - 表示鏈接還沒有創建。1 - 表示鏈接已創建,能夠進行通訊。2 - 表示鏈接正在進行關閉。3 - 表示鏈接已經關閉或者鏈接不能打開。
ws.bufferedAmount 只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,可是尚未發出的 UTF-8 文本字節數。

2.2 WebSocket 方法

屬性 描述
ws.send() 數據發送
ws.close() 關閉鏈接

2.3 Websocket 事件

屬性 描述
open 鏈接創建觸發
message 通訊時觸發
error 出錯觸發
close 關閉鏈接觸發

2.4 代碼實現

假設咱們在本地8080端口打開了websocket服務,那麼,下面代碼能夠在瀏覽器中實現和這個服務的通訊:github

<body>
  <script>
    var ws = new WebSocket("ws://localhost:8080/");
    // 創建鏈接觸發
    ws.onopen = function () {
      ws.send("open ws");
      console.log("open ws");
    };

    // 接收服務端數據觸發
    ws.onmessage = function (evt) {
      var data = evt.data;
      console.log("Data is ", data);
    };

    // 斷開鏈接觸發
    ws.onclose = function () {
      console.log("close ws");
    };
  </script>
</body>

3 WebSocket 服務端

關於服務端實現,根據技術選型不一樣,能夠選用不一樣的庫和包。我這裏使用的是 nodews庫來websocket服務端。

阮一峯的博文提到的socket.io庫,在瀏覽器端的寫法不兼容原生API,準確來講,它們本身實現了一套websocket。因此,使用的時候先後端都應該引用第三方庫。這樣就形成了代碼遷移性,嚴重降低。web

綜上所述,ws庫有如下優勢:ajax

  1. 兼容性好,兼容瀏覽器原生API
  2. 長期維護,效果穩定
  3. 使用方便(往下看就知道了)

4 實現羣聊

4.1 羣聊 服務端實現

首先,在命令行中,安裝ws庫: npm install ws --save

如今,利用ws來實現一個監聽8080端口的websocket服務器,講解都在代碼註釋裏,一目瞭然

const PORT = 8080; // 監聽端口
const WebSocket = require("ws"); // 引入 ws 庫

const wss = new WebSocket.Server({ port: PORT }); // 聲明wss對象

/**
 * 向除了自己以外全部客戶端發送消息,實現羣聊功能
 * @param {*} data 要發送的數據
 * @param {*} ws 客戶端鏈接對象
 */
wss.broadcastToElse = function broadcast(data, ws) { 
  wss.clients.forEach(function each(client) {
    if (client !== ws && client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
};

/* 客戶端接入,觸發 connection */
wss.on("connection", function connection(ws, req) {
  let ip = req.connection.remoteAddress; // 經過req對象能夠得到客戶端信息,好比:ip,headers等

  /* 客戶端發送消息,觸發 message */
  ws.on("message", function incoming(message) { 
    ws.send(message); // 向客戶端發送消息
    wss.broadcastToElse(message, ws); // 向 其餘的 客戶端發送消息,實現羣聊效果
  });

});

4.2 羣聊 客戶端實現

爲了方便編寫,這裏引入了jquerybootstrap這兩個庫,只須要關注js代碼便可。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>羣聊</title>
  <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  <script src="https://cdn.bootcss.com/jquery/3.3.0/jquery.min.js"></script>
</head>
<body>
  <div class="container">
    <textarea class="form-control" rows="30" disabled="disabled" id="show-area"></textarea>
    <input type="text" class="form-control" placeholder="請輸入聊天內容" id="chat-input">
    <button type="button" class="btn btn-info" id="send-btn">發送</button>
  </div>
  <script>
    var userName = parseInt(Math.random() * 1000, 10) // 隨機用戶名, 以標識身份
    
    var sendBtn = $("#send-btn"), // 發送信息按鈕
      chatInput = $("#chat-input"), // 聊天信息輸入框
      showArea = $("#show-area") // 聊天信息展現框

    var ws = new WebSocket("ws://localhost:8080/") // 初始化WebSocket對象

    sendBtn.on("click", function () {
      var content = chatInput.val()
      if (content.length === 0) {
        return alert("請不要輸入空白內容")
      }
      content = "At " + (new Date()).toString() + "\n" + "來自用戶" + userName + "\n" + content // 拼接用戶信息、時間信息和消息
      ws.send(content) // 發送消息
      chatInput.val("") // 清空輸入框
    })

    ws.onopen = function () { console.log("Conncet open") }
    ws.onmessage = function (evt) {
      var data = evt.data
      showArea.val(showArea.val() + data + "\n\n") // 刷新聊天信息展現框:顯示羣聊信息
    }
    ws.onclose = function () { console.log("Connect close") }
  </script>
</body>
</html>

4.3 羣聊 效果展現

首先啓動咱們的服務端代碼:node server.js 。其中,server.js是放置服務端代碼的文件。

而後,咱們打開2次編寫的html代碼,這至關於,打開2個客戶端。來檢測羣聊功能。

效果圖

5. 相關資料

本篇文章來自董沅鑫的我的網站,引用、轉載請指明出處

查看更多知識,或者技術交流:請訪問godbmw.com

相關文章
相關標籤/搜索