當前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請求,然而並非每次都能返回所需的新數據。當同時發起的請求達到必定數目時,會對服務器形成較大負擔。
客戶端發送一個request後,服務器拿到這個鏈接,若是有消息,才返回response給客戶端。沒有消息,就一直不返回response。以後客戶端再次發送request, 重複上次的動做。
http協議的特色是服務器不能主動聯繫客戶端,只能由客戶端發起。它的被動性預示了在完成雙向通訊時須要不停的鏈接或鏈接一直打開,這就須要服務器快速的處理速度或高併發的能力,是很是消耗資源的。
websocket是HTML5的一個新協議,它容許服務端向客戶端傳遞信息,實現瀏覽器和客戶端雙工通訊
由於 HTTP 協議有一個缺陷:通訊只能由客戶端發起。 舉例來講,咱們想了解今天的天氣,只能是客戶端向服務器發出請求,服務器返回查詢結果。HTTP 協議作不到服務器主動向客戶端推送信息。這種單向請求的特色,註定了若是服務器有連續的狀態變化,客戶端要獲知就很是麻煩。咱們只能使用"輪詢":每隔一段時候,就發出一個詢問,輪詢的效率低,很是浪費資源(由於必須不停鏈接,或者 HTTP 鏈接始終打開)。所以,工程師們一直在思考,有沒有更好的方法。WebSocket 就是這樣發明的。
服務器能夠主動向客戶端推送信息,客戶端也能夠主動向服務器發送信息,是真正的雙向平等對話,屬於服務器推送技術的一種。
跨平臺的WebSocket通訊庫,具備先後端一致的API,能夠觸發和響應自定義的事件。socket.io最核心的兩個api就是emit 和 on了 ,服務端和客戶端都有這兩個api。經過 emit 和 on能夠實現服務器與客戶端之間的雙向通訊。
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>複製代碼