前端面試題:你知道websocket嗎?

如下都是拾人牙慧做爲參考學習總結

傳統輪詢(Traditional Polling)

當前Web應用中較常見的一種持續通訊方式,一般採起 setInterval 或者 setTimeout 實現。例如若是咱們想要定時獲取並刷新頁面上的數據,能夠結合Ajax寫出以下實現:
setInterval(function() {
    $.get("/path/to/server", function(data, status) {
        console.log(data);
    });
}, 10000);複製代碼

上面的程序會每隔10秒向服務器請求一次數據,並在數據到達後存儲。這個實現方法一般能夠知足簡單的需求,然而同時也存在着很大的缺陷:在網絡狀況不穩定的狀況下,服務器從接收請求、發送請求到客戶端接收請求的總時間有可能超過10秒,而請求是以10秒間隔發送的,這樣會致使接收的數據到達前後順序與發送順序不一致。因而出現了採用 setTimeout 的輪詢方式:javascript

function poll() {
    setTimeout(function() {
        $.get("/path/to/server", function(data, status) {
            console.log(data);
            // 發起下一次請求
            poll();
        });
    }, 10000);
}複製代碼

程序首先設置10秒後發起請求,當數據返回後再隔10秒發起第二次請求,以此類推。這樣的話雖然沒法保證兩次請求之間的時間間隔爲固定值,可是能夠保證到達數據的順序。html

缺陷

程序在每次請求時都會新建一個HTTP請求,然而並非每次都能返回所需的新數據。當同時發起的請求達到必定數目時,會對服務器形成較大負擔。

長輪詢(long poll)

客戶端發送一個request後,服務器拿到這個鏈接,若是有消息,才返回response給客戶端。沒有消息,就一直不返回response。以後客戶端再次發送request, 重複上次的動做。

總結

http協議的特色是服務器不能主動聯繫客戶端,只能由客戶端發起。它的被動性預示了在完成雙向通訊時須要不停的鏈接或鏈接一直打開,這就須要服務器快速的處理速度或高併發的能力,是很是消耗資源的。

什麼是websocket?

websocket是HTML5的一個新協議,它容許服務端向客戶端傳遞信息,實現瀏覽器和客戶端雙工通訊

故事

由於 HTTP 協議有一個缺陷:通訊只能由客戶端發起。 舉例來講,咱們想了解今天的天氣,只能是客戶端向服務器發出請求,服務器返回查詢結果。HTTP 協議作不到服務器主動向客戶端推送信息。這種單向請求的特色,註定了若是服務器有連續的狀態變化,客戶端要獲知就很是麻煩。咱們只能使用"輪詢":每隔一段時候,就發出一個詢問,輪詢的效率低,很是浪費資源(由於必須不停鏈接,或者 HTTP 鏈接始終打開)。所以,工程師們一直在思考,有沒有更好的方法。WebSocket 就是這樣發明的。

websocket的特色

服務器能夠主動向客戶端推送信息,客戶端也能夠主動向服務器發送信息,是真正的雙向平等對話,屬於服務器推送技術的一種。
  • 與 HTTP 協議有着良好的兼容性。默認端口也是 80 和 443 ,而且握手階段採用 HTTP 協議,所以握手時不容易屏蔽,能經過各類 HTTP 代理服務器。 
  • 創建在TCP協議基礎之上,和http協議同屬於應用層
  • 數據格式比較輕量,性能開銷小,通訊高效。 
  • 能夠發送文本,也能夠發送二進制數據。 
  • 沒有同源限制,客戶端能夠與任意服務器通訊
  • 協議標識符是ws(若是加密,則爲wss),服務器網址就是 URL,如ws://localhost:8023

跨平臺的WebSocket通訊庫socket.io

跨平臺的WebSocket通訊庫,具備先後端一致的API,能夠觸發和響應自定義的事件。socket.io最核心的兩個api就是emit 和 on了 ,服務端和客戶端都有這兩個api。經過 emit 和 on能夠實現服務器與客戶端之間的雙向通訊。
  • emit :發射一個事件,第一個參數爲事件名,第二個參數爲要發送的數據,第三個參數爲回調函數(如需對方接受到信息後當即獲得確認時,則須要用到回調函數)。 
  • on :監聽一個 emit 發射的事件,第一個參數爲要監聽的事件名,第二個參數爲回調函數,用來接收對方發來的數據,該函數的第一個參數爲接收的數據。

服務端

var app = require('express')();
var http = require('http');
var socketio  = require("socket.io");
const server = http.createServer(app)
const io = socketio(server)
var count = 0;
// WebSocket 鏈接服務器
io.on('connection', (socket)=> {
    //// 全部的事件觸發響應都寫在這裏
    setInterval(()=>{
        count++
        //向創建該鏈接的客戶端發送消息
        socket.emit('mynameEv', { name:"你我貸"+count})
    },1000)
    //監聽客戶端發送信息
    socket.on('yournameEv', function (data) {
        console.log(data)
    })
})

app.get('/', function (req, res) {
    res.sendfile(__dirname + '/index.html');
});
// 啓用3000端口
server.listen(3000)複製代碼

客戶端

<body>
   <div id="myname"></div>
    <script src="http://localhost:3000/socket.io/socket.io.js"></script>
   <script>
      var count = 0;
      const socket = io.connect('http://localhost:3000')
      socket.on('mynameEv', (data)=>{
          document.getElementById("myname").innerHTML = data.name;
         console.log(data.name)
         setInterval(()=>{
                count++
                socket.emit('yournameEv', { name:"飛旋"+count})
         },1000)

      })
   </script>
</body>複製代碼




相關文章
相關標籤/搜索