我有一个简单的聊天应用程序使用socket。非常类似的socket聊天官方演示。当用户最小化页面或打开另一个应用程序或页面时,Socket io会在所有移动浏览器上进行ping超时。
在我的web应用程序中,无论何时,用户单击移动上的chrome/firefox/safari浏览器上的文件输入上传,就会打开“电话”对话框,从厨房中选择要选择和上传的文件。在此期间(由于可见性,我的聊天页面失去了焦点),当用户正在搜索文件时,在精确30秒后,socket客户端发出ping超时,并且person聊天被断开。
在我的应用程序级别,如果socket io出于任何原因进入ping超时,我将重新连接,但这并不能解决我的问题,因为如果用户在31秒后单击1个文件,那么该图像文件就不会在聊天中发送,因为socket io在这段时间内超时,当用户的焦点回到浏览器选项卡时,重新连接需要几秒钟。所以文件上传操作丢失了,因为文件是上传的,但是socket io连接处于ping超时状态。因此,当它重新连接时,所选的文件上载永远不会发送给其他连接的用户。
我试着在用户的页面焦点熄灭时,使用以下代码进行检测,
document.addEventListener("visibilitychange", onchange);然后,一旦页面不在焦点上,我就使用setinterval将我的自定义心跳事件发送到服务器代码。(只是为了防止socket与服务器对话以保持连接正常)。这对于桌面浏览器来说很好,但在所有移动浏览器上,只要用户页面不在焦点,即如果用户最小化浏览器,打开一个新应用程序,或去选择文件上传屏幕,socket io超时30秒后,有时甚至比这更快。
我的客户js代码:
var beating;
//function to detect if user gone out of page
//startSimulation and pauseSimulation defined elsewhere
function handleVisibilityChange() {
//socket = this.socket;
if (document.hidden) {
// console.log();
$('#logwrapper').prepend(" üser is outside \n ", socket.id);
//emit on server after every 10 seconds
beating = setInterval(function () {
$('#logwrapper').prepend(" inside interval emitting");
socket.emit('heartbeat', { data: "a" });
}, 15000)
} else {
//console.log("üser is in");
$('#logwrapper').prepend(" üser is in \n ", socket.id);
console.log("çlearing inteval beating from visiblity");
clearInterval(beating);
}
}
document.addEventListener("visibilitychange", handleVisibilityChange, false);和我的server.js代码
//socket events for heartbeat
socket.on("heartbeat", function (data) {
console.log("socket is outside ", data, socket.id);
});
//socket events for heartbeat , just log it so that my client remains active and keep communicating with server, to avoid socket io timeout我也尝试过调整我的socket io服务器和客户端超时信任,但这并没有什么不同,在用户最小化移动、合唱、firefox和safari上的浏览器页面之后,socket io客户端在30秒左右后发出超时。
如何增加这个超时,以便socket连接在更长的时间内保持活动(不要平超时)?
以下是我对socket的server.js信任:
var io = require("socket.io")(
231, {
transports: ["websocket", "polling"]
},
server, {
path: '/socket.io',
serveClient: true,
// below are engine.IO options
pingInterval: 25000, //was 10k, how many ms before sending a new ping packet, => how often to send a ping
pingTimeout: 30000, //should be above 30k to fix disconnection issue how many ms without a pong packet to consider the connection closed
upgradeTimeout: 20000, // default value is 10000ms, try changing it to 20k or more
agent: false,
cookie: false,
rejectUnauthorized: false,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
maxHttpBufferSize: 100000000 //100 mb
}
);我的socket io客户吐露道:
this.socket = io.connect('https://appurl.com', {
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
reconnectionAttempts: Infinity,
//our site options
transports: ["polling", "websocket"],
secure: true,
rejectUnauthorized: false,
forceNew: false,
timeout: 60000
});基本上,在所有的移动浏览器上,只要页面脱离焦点,我的JS代码就会停止执行,每当页面再次聚焦时,JS退出就会恢复,看起来它不存在设置间隔或设置超时的问题。如何继续执行我的客户端JS代码以防止socket执行ping超时?
我还使用settimeout ( https://codepen.io/Suhoij/pen/jAxtn )尝试了类似的逻辑。
这段代码适用于所有移动浏览器的代码,即使我将手机上的页面最小化并再次返回,计时器仍在执行,但在我的应用程序上运行时相同的代码在我的代码中不起作用。为什么?当页面不在焦点时,socket是否暂停了我的所有client.js代码?还是我的逻辑不对?我还试着在每2秒向所有客户端发送一次来自我的server.js的事件,但是当页面不在移动环境中时,发射停止:/
发布于 2022-03-16 20:46:13
关于我在socket.io 4.4.1上必须做的事情
我使用管理器事件处理移动https://socket.io/docs/v4/client-api/#event-error上的断开连接。
import io from "socket.io-client";
socket = io(socketUrl, {
reconnectionAttempts,
reconnectionDelay,
});
//for the actual websocket having an error attempt to reconnect
socket.io.on("error", (error) => {
// ...
console.log('socket io error on ' + error);
socket = io(socketUrl, {
reconnectionAttempts,
reconnectionDelay,
});
});
let socketArray = ['reconnect', 'reconnect_attempt', 'reconnect_error', 'reconnect_failed'];
for(let i = 0, len = socketArray.length; i < len; i++) {
socket.io.on(socketArray[i], (attempt) => {
// ...
console.log(socketArray[i] + ' socket io on ' + attempt);
});
}这使得它如果websocket管理器有一个错误,它将重新连接。当我在浏览器上的套接字好,关闭我的iphone,回到浏览器,在那里它重新连接使用socket.on('connection'罚款,然后当我关闭我的手机屏幕,然后再回去,我会得到这个错误的WebSocket connection to 'wss://mysocketserver.com' failed: The operation couldn’t be completed. (kNWErrorDomainPOSIX error 53 - Software caused connection abort),通过添加socket.io.on("error",让它重新连接,然后它将正确地重新建立每一样东西。
https://stackoverflow.com/questions/58667207
复制相似问题