服務器與客戶端的實時通訊

服務器與客戶端的實時通訊

咱們在作聊天室的時候,會須要用到實時通訊,當服務端向客戶端提早聲明,發送的是流信息的時候,HTTP 協議能夠容許服務器向客戶端發送消息,由於一次性發送不完,須要接二連三的發送,客戶端不會關閉鏈接,會一直等着服務器發送新的數據流。javascript

服務端與客戶端的實時通訊,主要有如下三種解決方案:css

輪詢

前端能夠在本身的頁面進行輪詢(定時)調用後端的接口,而後觸發後端給前端返回消息,雖然能夠解決先後端實時推送的數據問題,可是這樣作並非一個最優解,使用 WebSocket 和 SSE 更好一點。html

WebSocket

WebSocket 是一個全雙工通道,客戶端能夠給服務端發送消息,而且能夠接收服務端的消息,服務端也能夠給客戶端發送消息,接收客戶端的消息。前端

websocket 有不少特色:java

  1. 創建在 TCP 協議之上,服務器端的實現比較容易
  2. 與 HTTP 協議有着良好的兼容性。默認端口也是 80 和 443,而且握手階段採用 HTTP 協議,所以握手時不容易屏蔽,能經過各類 HTTP 代理服務器。
  3. 數據格式比較輕量,性能開銷小,通訊高效。
  4. 能夠發送文本,也能夠發送二進制數據。
  5. 沒有同源限制,客戶端能夠與任意服務器通訊。
  6. 協議標識符是 ws(若是加密,則爲 wss),服務器網址就是 URL。

像直播的聊天室都是 WebSocket 作的。咱們在使用 WebSocket 的時候,可使用 socket.io 這個庫,會方便不少。在前端頁面須要依靠 socket.io.js,node 要依靠socket.io的庫。node

用一個簡單的 socket.io 的例子,實現一下精簡版的互相通訊。廢話很少說,上代碼:web

server 端:後端

const Koa = require('koa');
const app = new Koa();
const server = require('http').Server(app.callback());
const io = require('socket.io')(server);
const port = 8081;

server.listen(process.env.PORT || port, () => {
  console.log(`app run at : http://127.0.0.1:${port}`);
});

io.on('connection', socket => {
  console.log('初始化成功!下面能夠用socket綁定事件和觸發事件了');
  socket.on('send', data => {
    console.log('客戶端發送的內容:', data);
    socket.emit('getMsg', '我是返回的消息... ...');
  });

  setInterval(() => {
    socket.emit('getMsg', '我是初始化3s後的返回消息... ...');
  }, 3000);
});
複製代碼

client 端:api

<!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>websocket示例</title>
  </head>
  <body>
    <button id="send">發送消息到服務器</button>
    <div>
      <h3>服務器響應的消息:</h3>
      <i id="msg"></i>
    </div>

    <script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
    <script> var socket = io('ws://localhost:8081'); var send = document.querySelector('#send'); var msg = document.querySelector('#msg'); socket.on('getMsg', data => { console.log('服務端消息:', data); msg.innerHTML += `${data} <br/>`; }); socket.on('message', data => { console.log('服務端消息:', data); // msg.innerHTML += `${data} <br/>`; }); send.onclick = () => { console.log('點擊了發送消息!'); socket.emit('send', 'hello'); }; </script>
  </body>
</html>
複製代碼
  • 前端經過 socket.on('事件名', callback)監聽到後端的觸發
  • 前端經過 socket.emit('事件名', '消息體')向後端發送消息
  • 後端經過 socket.emit('事件名', '消息體')向前端發送消息
  • 後端經過 socket.on('事件名', callback)接收前端發送來的消息
  • 後端經過 socket.on('disconnect')監聽退出事件
  • 後端能夠經過 socket.broadcast.emit('message', '消息內容')進行廣播

SSE(Server-Sent Events)

SSE 相對於 WebSocket 來講,沒有 WebSocket 那麼強大,由於 WebSocket 是全雙工通道,可是 SSE 是單向通道,只能服務器向瀏覽器發送信息。瀏覽器

可是 SSE 相對 WebSocket 來講,也有本身的優勢:

  1. 輕量級,使用簡單,沒有 WebSocket 的協議那麼複雜
  2. 默認斷線重連,WebSocket 須要本身去實現
  3. SSE 通常用來發送文本,若是發送二進制數據,須要編碼後傳輸,WebSocket 默認支持傳送二進制數據

具體的代碼示例能夠參考 javascript.ruanyifeng.com/htmlapi/eve…

相關文章
相關標籤/搜索