我们注意到Safari iOS在Websocket连接丢失时不调用Websocket事件的问题。我们的Web应用程序不知道Websocket的连接已经丢失。在Android设备上,一旦连接断开,就会触发close和error Websocket事件。
我们创造了一个快速的例子。
nodeJS中的Websocket服务器
const WebSocket = require('ws');
const wss = new WebSocket.Server({port: 8080});
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
ws.send(`You sent: ${message}`);
});
ws.on('close', function close() {
console.log('Client has disconnected');
});
});
简单客户端
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Example</title>
</head>
<body>
<h1>WebSocket Example</h1>
<div id="output"></div>
<form>
<label>
Message:
<input type="text" id="message">
</label>
<button type="submit" id="send">Send</button>
</form>
<script>
const output = document.getElementById('output');
const messageInput = document.getElementById('message');
const sendButton = document.getElementById('send');
const ws = new WebSocket('ws://localhost:8080');
ws.addEventListener('open', function (event) {
console.log((new Date()).toISOString(), '********************** OPEN **********************');
});
ws.addEventListener('close', function (event) {
console.log((new Date()).toISOString(), '********************** CLOSE **********************');
});
ws.addEventListener('error', function (event) {
console.log((new Date()).toISOString(), '********************** ERROR **********************');
});
ws.addEventListener('message', function (event) {
console.log((new Date()).toISOString(), '********************** MESSAGE **********************');
// Append the message to the output div
const message = document.createElement('p');
message.textContent = event.data;
output.appendChild(message);
});
sendButton.addEventListener('click', function (event) {
event.preventDefault();
const message = messageInput.value;
// Send the message to the server
ws.send(message);
});
</script>
</body>
</html>
当上面的代码运行时,iOS移动Safari在Websocket连接关闭时不会触发事件close
或error
。
关闭Websocket的示例如下:
- 一种飞机模式投放装置
- 关闭wifi路由器
- 关闭设备的WiFi
如前所述,这在Android和其他设备上运行良好,只有iOS Safari这样做,有人在他们的Web应用程序中遇到过这种情况吗?
- 编辑2023 05 18:**
有一个Webkit bug报告与此行为相关:https://bugs.webkit.org/show_bug.cgi?id=247943
一个临时的解决方法是处理window.onoffline事件来警告用户等。希望他们能尽快解决这个问题。
1条答案
按热度按时间z0qdvdin1#
我发现一个早期的问题https://bugs.chromium.org/p/chromium/issues/detail?id=197841。关键是关闭事件会延迟触发,延迟时间取决于操作系统、浏览器等。在我的环境中,关闭事件在关闭WiFi 12分钟后触发。我尝试了两种方法来解决它:
1.添加heartbeat,请参考https://github.com/websockets/ws/issues/1158#issuecomment-311321579
1.使用
window.addEventListener('offline',callback)
,在断开连接时在回调中执行某些操作