iOS - WebSocket关闭和错误事件未触发

iugsix8n  于 2023-06-23  发布在  iOS
关注(0)|答案(1)|浏览(274)

我们注意到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连接关闭时不会触发事件closeerror
关闭Websocket的示例如下:

  • 一种飞机模式投放装置
  • 关闭wifi路由器
  • 关闭设备的WiFi

如前所述,这在Android和其他设备上运行良好,只有iOS Safari这样做,有人在他们的Web应用程序中遇到过这种情况吗?

    • 编辑2023 05 18:**

有一个Webkit bug报告与此行为相关:https://bugs.webkit.org/show_bug.cgi?id=247943
一个临时的解决方法是处理window.onoffline事件来警告用户等。希望他们能尽快解决这个问题。

z0qdvdin

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),在断开连接时在回调中执行某些操作

相关问题