У меня есть простое приложение chat , использующее сокет io. Очень похоже на сокет io chat официальной демоверсии. Socket io переходит на таймаут ping во всех мобильных браузерах всякий раз, когда пользователь сворачивает страницу или открывает другое приложение, или страница выходит из строя.
В моем веб-приложении каждый раз, когда пользователь нажимает на загрузку ввода файла из своего chrome /Браузер Firefox / Safari на мобильном телефоне, он открывает диалоговое окно телефона, чтобы выбрать файл из камбуза для выбора и загрузки. В течение этого времени (моя страница чата выходит из фокуса из-за видимости), когда пользователь ищет файл, и через 30 секунд клиент Socket Io выдает тайм-аут пинга, и чат пользователя отключается.
На моем уровне приложения я делаю переподключение, если сокет io переходит в тайм-аут пинга по любой причине, но это не решает мою проблему, потому что, если пользователь нажимает на 1 файле через 31 секунду, тогда этофайл изображения не отправляется в чат, потому что сокет io истек в это время, и требуется несколько секунд для повторного подключения, когда пользователь снова переключается на вкладку браузера. Таким образом, действие загрузки файла потеряно, потому что файл загружен, но соединение сокета io было на таймауте ping. поэтому при повторном подключении выбранная загрузка файла никогда не отправляется другому подключенному пользователю.
Я пытался определить, когда отсутствует фокус страницы пользователя, используя этот код,
document.addEventListener("visibilitychange", onchange);
из Есть ли способ обнаружить, если окно браузера не активно в данный момент?
, а затем, когда страница не в фокусе, я использовал setinterval, чтобы передать свое пользовательское событие сердцебиения в код моего сервера. (просто чтобы сокет 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
Я также пытался настроить параметры сокета io server и client timeout, но этоне имеет никакого значения, после того как пользователь свернул страницу браузера на мобильном устройстве, chorme, firefox и safari, клиент Socket Io отправляет пинг через 30 секунд или около того,
Как я могу увеличить это время ожидания, такСоединение с сокетом io остается активным (не проверяйте время ожидания) в течение более длительного времени (сколько мне нужно)?
Вот мои настройки server.js для сокета io:
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 возобновляется,похоже, это не проблема с setinterval или settimeout. Как я могу продолжать выполнять свой клиентский JS-код, чтобы сокет io не делал тайм-аут пинга?
Я также попробовал аналогичную логику, используя settimeout, https://codepen.io/Suhoij/pen/jAxtn
этот код работает в codepen на всех мобильныхбраузеры, даже если я сверну эту страницу на своем мобильном телефоне и вернусь снова, таймер все еще работает, но тот же код, когда я запускаю свое приложение, он не работает в моем коде. Почему? Сокет io приостанавливает весь мой код client.js, когда страница не в фокусе? ИЛИ моя логика не верна? Я также пытался отправлять событие из моего server.js через каждые 2 секунды на все клиенты, но их испускание прекращалось, когда страница не находится в foucs на мобильном телефоне: /
Соответствующие проблемы с сокетом io: https://github.com/socketio/socket.io/issues/2769