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小时内与您取得联系。