3月30日消息,蘋果 iOS 16.4 系統已經向用戶推送,蘋果在這個版本中開放了 Web Push API。這意味著,網站可以通過 Safari 向用戶推送通知。
用 Safari 打開網頁,選擇下方的分享按鈕,再選擇添加到主屏幕,即可將網頁 icon 添加到手機屏幕,當收到通知后, icon 右上角可顯示通知數量。
這僅適用于添加到主屏幕的網頁,網頁使用 HTML5 標準 Web Push API 推送通知。
可以通過 設置>通知 來調整網頁權限,對于不想收到通知的網頁,可以關閉通知權限。
(8148716)
隨著 Web 的發展,用戶對于 Web 的實時推送要求也越來越高 ,比如,工業運行監控、Web 在線通訊、即時報價系統、在線游戲等,都需要將后臺發生的變化主動地、實時地傳送到瀏覽器端,而不需要用戶手動地刷新頁面。本文對過去和現在流行的 Web 實時推送技術進行了比較與總結。
HTTP 協議有一個缺陷:通信只能由客戶端發起。舉例來說,我們想了解今天的天氣,只能是客戶端向服務器發出請求,服務器返回查詢結果。HTTP 協議做不到服務器主動向客戶端推送信息。這種單向請求的特點,注定了如果服務器有連續的狀態變化,客戶端要獲知就非常麻煩。在WebSocket協議之前,有三種實現雙向通信的方式:輪詢(polling)、長輪詢(long-polling)和iframe流(streaming)。
1.輪詢(polling)
輪詢是客戶端和服務器之間會一直進行連接,每隔一段時間就詢問一次。其缺點也很明顯:連接數會很多,一個接受,一個發送。而且每次發送請求都會有Http的Header,會很耗流量,也會消耗CPU的利用率。
// 1.html
<div id="clock"></div>
<script>
let clockDiv = document.getElementById('clock');
setInterval(function(){
let xhr = new XMLHttpRequest;
xhr.open('GET','/clock',true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
clockDiv.innerHTML = xhr.responseText;
}
}
xhr.send();
},1000);
</script>
//輪詢 服務端
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)
長輪詢是對輪詢的改進版,客戶端發送HTTP給服務器之后,看有沒有新消息,如果沒有新消息,就一直等待。當有新消息的時候,才會返回給客戶端。在某種程度上減小了網絡帶寬和CPU利用率等問題。由于http數據包的頭部數據量往往很大(通常有400多個字節),但是真正被服務器需要的數據卻很少(有時只有10個字節左右),這樣的數據包在網絡上周期性的傳輸,難免對網絡帶寬是一種浪費。
// 2.html 服務端代碼同上
<div id="clock"></div>
<script>
let clockDiv = document.getElementById('clock')
function send() {
let xhr = new XMLHttpRequest()
xhr.open('GET', '/clock', true)
xhr.timeout = 2000 // 超時時間,單位是毫秒
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
//如果返回成功了,則顯示結果
clockDiv.innerHTML = xhr.responseText
}
send() //不管成功還是失敗都會發下一次請求
}
}
xhr.ontimeout = function() {
send()
}
xhr.send()
}
send()
</script>
3.iframe流(streaming)
iframe流方式是在頁面中插入一個隱藏的iframe,利用其src屬性在服務器和客戶端之間創建一條長連接,服務器向iframe傳輸數據(通常是HTML,內有負責插入信息的javascript),來實時更新頁面。
// 3.html
<body>
<div id="clock"></div>
<iframe src="/clock" style="display:none"></iframe>
</body>
//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(`
<script type="text/javascript">
parent.document.getElementById('clock').innerHTML = "${date}";//改變父窗口dom元素
</script>
`)
}, 1000)
})
app.listen(8080)
啟動本地服務,打開http://localhost:8080/3.html,得到如下結果:
上述代碼中,客戶端只請求一次,然而服務端卻是源源不斷向客戶端發送數據,這樣服務器維護一個長連接會增加開銷。
以上我們介紹了三種實時推送技術,然而各自的缺點很明顯,使用起來并不理想,接下來我們著重介紹另一種技術--websocket,它是比較理想的雙向通信技術。
1.什么是websocket
WebSocket是一種全新的協議,隨著HTML5草案的不斷完善,越來越多的現代瀏覽器開始全面支持WebSocket技術了,它將TCP的Socket(套接字)應用在了webpage上,從而使通信雙方建立起一個保持在活動狀態連接通道。
一旦Web服務器與客戶端之間建立起WebSocket協議的通信連接,之后所有的通信都依靠這個專用協議進行。通信過程中可互相發送JSON、XML、HTML或圖片等任意格式的數據。由于是建立在HTTP基礎上的協議,因此連接的發起方仍是客戶端,而一旦確立WebSocket通信連接,不論服務器還是客戶端,任意一方都可直接向對方發送報文。
初次接觸 WebSocket 的人,都會問同樣的問題:我們已經有了 HTTP 協議,為什么還需要另一個協議?
2.HTTP的局限性
3.WebSocket的特點
相對于傳統的HTTP每次請求-應答都需要客戶端與服務端建立連接的模式,WebSocket是類似Socket的TCP長連接的通訊模式,一旦WebSocket連接建立后,后續數據都以幀序列的形式傳輸。在客戶端斷開WebSocket連接或Server端斷掉連接前,不需要客戶端和服務端重新發起連接請求。在海量并發和客戶端與服務器交互負載流量大的情況下,極大的節省了網絡帶寬資源的消耗,有明顯的性能優勢,且客戶端發送和接受消息是在同一個持久連接上發起,實時性優勢明顯。
接下來我看下websocket如何實現客戶端與服務端雙向通信:
// websocket.html
<div id="clock"></div>
<script>
let clockDiv = document.getElementById('clock')
let socket = new WebSocket('ws://localhost:9999')
//當連接成功之后就會執行回調函數
socket.onopen = function() {
console.log('客戶端連接成功')
//再向服務 器發送一個消息
socket.send('hello') //客戶端發的消息內容 為hello
}
//綁定事件是用加屬性的方式
socket.onmessage = function(event) {
clockDiv.innerHTML = event.data
console.log('收到服務器端的響應', event.data)
}
</script>
// 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服務器,監聽了9999端口
let wsServer = new WebSocketServer({ port: 9999 })
//監聽客戶端的連接請求 當客戶端連接服務器的時候,就會觸發connection事件
//socket代表一個客戶端,不是所有客戶端共享的,而是每個客戶端都有一個socket
wsServer.on('connection', function(socket) {
//每一個socket都有一個唯一的ID屬性
console.log(socket)
console.log('客戶端連接成功')
//監聽對方發過來的消息
socket.on('message', function(message) {
console.log('接收到客戶端的消息', message)
socket.send('服務器回應:' + message)
})
})
啟動本地服務,打開http://localhost:3000/websocket.html,得到如下結果:
綜上所述:Websocket協議不僅解決了HTTP協議中服務端的被動性,即通信只能由客戶端發起,也解決了數據同步有延遲的問題,同時還帶來了明顯的性能優勢,所以websocket 是Web 實時推送技術的比較理想的方案,但如果要兼容低版本瀏覽器,可以考慮用輪詢來實現。
時消息推送是指在瀏覽器中展示實時更新的消息,而無需刷新頁面。以下是七種實現Web實時消息推送的方案:
1、WebSocket: WebSocket是HTML5中新增的一種技術,它允許瀏覽器和服務器之間進行全雙工通信,可以在服務器端推送消息給客戶端,同時客戶端也可以推送消息給服務器端。
2、Server-Sent Events(SSE): SSE也是HTML5中新增的一種技術,它允許服務器端發送一系列事件到客戶端,這些事件可以是JSON、XML等格式,客戶端通過事件監聽器來處理這些事件,實現實時推送。
3、Long Polling: 在Long Polling中,瀏覽器向服務器發送一個請求,服務器不會立即返回結果,而是等待數據準備好時再返回,瀏覽器收到數據后再重新發送請求,循環往復。
4、WebRTC: WebRTC是一個實時通信技術,它可以在兩個瀏覽器之間建立點對點的數據通道,可以實現實時消息推送。
5、Comet: Comet是一種長連接技術,通過HTTP請求來保持連接,當服務器有新消息時,就發送給客戶端,從而實現實時推送。
6、SignalR: SignalR是一個開源的實時通信框架,它可以實現實時消息推送、廣播和持久連接等功能。
7、MQTT: MQTT是一個輕量級的消息傳輸協議,它可以在低帶寬、不穩定的網絡環境下實現可靠的消息傳輸,適用于物聯網等場景。
以上是七種實現Web實時消息推送的方案,可以根據不同的需求選擇合適的方案。
關注查看更多技術架構文章!每天持續更新,干貨不斷!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。