新聞中心
前言
隨著 Web 的發(fā)展,用戶對于 Web 的實時推送要求也越來越高 ,比如,工業(yè)運行監(jiān)控、Web 在線通訊、即時報價系統(tǒng)、在線游戲等,都需要將后臺發(fā)生的變化主動地、實時地傳送到瀏覽器端,而不需要用戶手動地刷新頁面。本文對過去和現(xiàn)在流行的 Web 實時推送技術進行了比較與總結。

一、雙向通信
HTTP 協(xié)議有一個缺陷:通信只能由客戶端發(fā)起。舉例來說,我們想了解今天的天氣,只能是客戶端向服務器發(fā)出請求,服務器返回查詢結果。HTTP 協(xié)議做不到服務器主動向客戶端推送信息。這種單向請求的特點,注定了如果服務器有連續(xù)的狀態(tài)變化,客戶端要獲知就非常麻煩。在WebSocket協(xié)議之前,有三種實現(xiàn)雙向通信的方式:輪詢(polling)、長輪詢(long-polling)和iframe流(streaming)。
1.輪詢(polling)
輪詢是客戶端和服務器之間會一直進行連接,每隔一段時間就詢問一次。其缺點也很明顯:連接數(shù)會很多,一個接受,一個發(fā)送。而且每次發(fā)送請求都會有Http的Header,會很耗流量,也會消耗CPU的利用率。
- 優(yōu)點:實現(xiàn)簡單,無需做過多的更改
- 缺點:輪詢的間隔過長,會導致用戶不能及時接收到更新的數(shù)據(jù);輪詢的間隔過短,會導致查詢請求過多,增加服務器端的負擔
- // 1.html
- //輪詢 服務端
- let express = require('express');
- let app = express();
- app.use(express.static(__dirname));
- app.get('/clock',function(req,res){
- res.end(new Date().toLocaleString());
- });
- app.listen(8080);
啟動本地服務,打開http://localhost:8080/1.html,得到如下結果:
2.長輪詢(long-polling)
長輪詢是對輪詢的改進版,客戶端發(fā)送HTTP給服務器之后,看有沒有新消息,如果沒有新消息,就一直等待。當有新消息的時候,才會返回給客戶端。在某種程度上減小了網(wǎng)絡帶寬和CPU利用率等問題。由于http數(shù)據(jù)包的頭部數(shù)據(jù)量往往很大(通常有400多個字節(jié)),但是真正被服務器需要的數(shù)據(jù)卻很少(有時只有10個字節(jié)左右),這樣的數(shù)據(jù)包在網(wǎng)絡上周期性的傳輸,難免對網(wǎng)絡帶寬是一種浪費。
- 優(yōu)點:比 Polling 做了優(yōu)化,有較好的時效性
- 缺點:保持連接會消耗資源; 服務器沒有返回有效數(shù)據(jù),程序超時。
- // 2.html 服務端代碼同上
3.iframe流(streaming)
iframe流方式是在頁面中插入一個隱藏的iframe,利用其src屬性在服務器和客戶端之間創(chuàng)建一條長連接,服務器向iframe傳輸數(shù)據(jù)(通常是HTML,內有負責插入信息的javascript),來實時更新頁面。
- 優(yōu)點:消息能夠實時到達;瀏覽器兼容好
- 缺點:服務器維護一個長連接會增加開銷;IE、chrome、Firefox會顯示加載沒有完成,圖標會不停旋轉。
- // 3.html
- //iframe流
- let express = require('express')
- let app = express()
- app.use(express.static(__dirname))
- app.get('/clock', function(req, res) {
- setInterval(function() {
- let date = new Date().toLocaleString()
- res.write(`
- `)
- }, 1000)
- })
- app.listen(8080)
啟動本地服務,打開http://localhost:8080/3.html,得到如下結果:
上述代碼中,客戶端只請求一次,然而服務端卻是源源不斷向客戶端發(fā)送數(shù)據(jù),這樣服務器維護一個長連接會增加開銷。
以上我們介紹了三種實時推送技術,然而各自的缺點很明顯,使用起來并不理想,接下來我們著重介紹另一種技術--websocket,它是比較理想的雙向通信技術。
二、WebSocket
1.什么是websocket
WebSocket是一種全新的協(xié)議,隨著HTML5草案的不斷完善,越來越多的現(xiàn)代瀏覽器開始全面支持WebSocket技術了,它將TCP的Socket(套接字)應用在了webpage上,從而使通信雙方建立起一個保持在活動狀態(tài)連接通道。
一旦Web服務器與客戶端之間建立起WebSocket協(xié)議的通信連接,之后所有的通信都依靠這個專用協(xié)議進行。通信過程中可互相發(fā)送JSON、XML、HTML或圖片等任意格式的數(shù)據(jù)。由于是建立在HTTP基礎上的協(xié)議,因此連接的發(fā)起方仍是客戶端,而一旦確立WebSocket通信連接,不論服務器還是客戶端,任意一方都可直接向對方發(fā)送報文。
初次接觸 WebSocket 的人,都會問同樣的問題:我們已經(jīng)有了 HTTP 協(xié)議,為什么還需要另一個協(xié)議?
2.HTTP的局限性
- HTTP是半雙工協(xié)議,也就是說,在同一時刻數(shù)據(jù)只能單向流動,客戶端向服務器發(fā)送請求(單向的),然后服務器響應請求(單向的)。
- 服務器不能主動推送數(shù)據(jù)給瀏覽器。這就會導致一些高級功能難以實現(xiàn),諸如聊天室場景就沒法實現(xiàn)。
3.WebSocket的特點
- 支持雙向通信,實時性更強
- 可以發(fā)送文本,也可以發(fā)送二進制數(shù)據(jù)
- 減少通信量:只要建立起WebSocket連接,就希望一直保持連接狀態(tài)。和HTTP相比,不但每次連接時的總開銷減少,而且由于WebSocket的首部信息很小,通信量也相應減少了
相對于傳統(tǒng)的HTTP每次請求-應答都需要客戶端與服務端建立連接的模式,WebSocket是類似Socket的TCP長連接的通訊模式,一旦WebSocket連接建立后,后續(xù)數(shù)據(jù)都以幀序列的形式傳輸。在客戶端斷開WebSocket連接或Server端斷掉連接前,不需要客戶端和服務端重新發(fā)起連接請求。在海量并發(fā)和客戶端與服務器交互負載流量大的情況下,極大的節(jié)省了網(wǎng)絡帶寬資源的消耗,有明顯的性能優(yōu)勢,且客戶端發(fā)送和接受消息是在同一個持久連接上發(fā)起,實時性優(yōu)勢明顯。
接下來我看下websocket如何實現(xiàn)客戶端與服務端雙向通信:
- // websocket.html
- // websocket.js
- let express = require('express')
- let app = express()
- app.use(express.static(__dirname))
- //http服務器
- app.listen(3000)
- let WebSocketServer = require('ws').Server
- //用ws模塊啟動一個websocket服務器,監(jiān)聽了9999端口
- let wsServer = new WebSocketServer({ port: 9999 })
- //監(jiān)聽客戶端的連接請求 當客戶端連接服務器的時候,就會觸發(fā)connection事件
- //socket代表一個客戶端,不是所有客戶端共享的,而是每個客戶端都有一個socket
- wsServer.on('connection', function(socket) {
- //每一個socket都有一個***的ID屬性
- console.log(socket)
- console.log('客戶端連接成功')
- //監(jiān)聽對方發(fā)過來的消息
- socket.on('message', function(message) {
- console.log('接收到客戶端的消息', message)
- socket.send('服務器回應:' + message)
- })
- })
啟動本地服務,打開http://localhost:3000/websocket.html,得到如下結果:
三、Web 實時推送技術的比較
綜上所述:Websocket協(xié)議不僅解決了HTTP協(xié)議中服務端的被動性,即通信只能由客戶端發(fā)起,也解決了數(shù)據(jù)同步有延遲的問題,同時還帶來了明顯的性能優(yōu)勢,所以websocket 是Web 實時推送技術的比較理想的方案,但如果要兼容低版本瀏覽器,可以考慮用輪詢來實現(xiàn)。
當前標題:淺談Web實時推送技術,有對比,有總結
標題鏈接:http://www.dlmjj.cn/article/cospjhc.html


咨詢
建站咨詢
