gpt4 book ai didi

javascript - Websocket 连接在 Safari iOS 中随机挂起

转载 作者:行者123 更新时间:2023-11-30 11:43:01 25 4
gpt4 key购买 nike

关于 iOS 设备上的 websockets,我有一个相当奇怪和具体的问题。

我正在开发一个基于浏览器的网络应用程序,它通过网络套接字与网络服务器通信。对于客户端,使用浏览器的 native websocket,因此不涉及任何库(没有 socket.io 等)。

在服务器端,我将 Node.js 与 ws module 一起使用作为 websocket 服务器。

在桌面浏览器和 Android 设备上一切正常,但在 iOS 上连接经常“挂起”,这意味着浏览器不响应在 websocket 连接上收到的消息。 Websocket 的“onmessage”处理程序不会被触发。

但是在调试服务器时,我可以清楚地看到消息是如何离开服务器并发送到浏览器的,但是当这个问题发生时,在 Safari 上没有任何反应。消息似乎“卡在”了设备中的某处,因为如果我在 GUI 上触发另一个事件(例如移动 slider 或单击按钮),则会立即执行“onmessage”。由于 iOS 上的所有浏览器共享相同的后端,因此在 Safari、Chrome 和 Firefox 上都会发生这种情况。

我承认消息可以变得非常大,即它们可以长到大约 100kb。我读到一些 websocket 实现存在这些量级的问题,因此我尝试在应用程序级别将它们分成几个 block ,但到目前为止没有成功。

也许值得一提的是服务器操作系统是 Windows。


这是我的简单客户端代码(摘要):

var socket = new WebSocket("ws://myurl.com");

socket.onmessage = function(e) {
// Sometimes gets stuck before calling this handler.
// Can be resolved with triggering any event on the UI.

processData(e.data);
}

socket.onerror = function(e) {
logError(e);
}

socket.onclose = function(e) {
cleanUp();
}

服务器端看起来像这样:

var webServer = require("http")
.createServer()
.listen(80, "0.0.0.0", function () {
console.log("Listening on port " + 80);
});

var WebSocketServer = require("ws").Server;

var wss = new WebSocketServer({server: webServer});

wss.on("connection", function(ws) {
ws.on("message", function(message) {
processMessage(message);
});
});

到目前为止我尝试了什么

  • 按照提到的方式使用内容安全策略 here (但这可能更像是一个 Meteor/Cordova 问题)

  • 在应用程序级别将消息拆分为 block (said here)

  • 发送一些虚拟确认字节或禁用 Nagle 算法(如建议 here )

  • 将 onmessage 回调包装到 setTimeout() ( here )

  • 协议(protocol) WS 或 WSS 没有区别

  • 运行高速公路测试套件。有时它通过了所有测试,有时由于超时或执行时间太长而导致其中一些失败


有人可以给我一些提示或对此类问题有经验吗?

更新 02.02.017

另外值得一提的是,我的应用程序是一个通过 requestAnimationFrame 在循环中渲染的 3D 应用程序。

经过多天的研究,我发现 requestAnimationFrame + WebSockets onmessage handler 似乎存在问题。

明天我会更新我的发现。

最佳答案

如果通过 requestAnimationFrame 创建 3D 渲染循环并且同时应用程序正在使用 Websocket 的 onmessage 处理程序接收数据,则似乎会出现此问题。

一个解决方案是将 requestAnimationFrame 替换为 setTimeout 的交替调用(参见下面的示例),模仿 requestAnimationFramesetTimeout 或使用 setInterval 作为解决方法。

我在 chromium 的问题跟踪器(herethere)中找到了这个错误的证据,所以我不知道这个错误与 Apple 的 Webkit 有多大关系,但至少那里描述的症状非常相似并且解决方案/解决方法也对我有帮助。

下面我引用了这个 source 的解决方案所有学分都转到那里的评论#30:

var altframe = true, frametime = 0, lastframe = Date.now();

function Run() {
frametime = Date.now() - lastframe;
lastframe = Date.now();

if (!altframe)
setTimeout(Run,frametime);
// Hard-scheduled based on timing of last frame, must schedule before sim+render.

/*

SIM AND RENDER CODE

*/

if (altframe) {
window.requestAnimationFrame(Run);
// Normal timing, called after next paint.
altframe = false; // Alternate frame will be timed based on the next one.
}
else {
altframe = true; // Because we can't switch it above.
}
};

Run(); // As if we just had our setTimeout fire, altframe should be true

关于javascript - Websocket 连接在 Safari iOS 中随机挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41940884/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com