I have a rather strange and specific problem regarding websockets on iOS devices.
I'm developing a browser based web app which communicates with a web server via websockets. For the client side the browser's native websocket is used, so there is no library involved (no socket.io etc.).
On the server side I am using Node.js with the ws module as a websocket server.
On desktop browsers and Android devices everything works fine, but on iOS the connection quite often "hangs", meaning the browser doesn't respond to messages received on the websocket connection. The websocket's "onmessage" handler doesn't get fired.
However when debugging the server, I can clearly see how the message leaves the server and is sent to the browser, but when this problem occurs then on Safari nothing happens. It seems like the message is "stuck" somewhere in the device, because if I trigger another event on the GUI (e.g. moving a slider or clicking buttons) then the "onmessage" is executed immediately. As all browsers on iOS share the same backend, this happens on Safari, Chrome and Firefox.
I admit that the messages can become very big, i.e. they can become some 100kb long. I read that some websocket implementations have problems with these magnitudes, so I have tried splitting them into several chunks on application level, but so far without success.
Maybe it's worth to mention that the server OS is Windows.
This is my simple client side code (abstract):
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();
}
The server side looks something like this:
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);
});
});
What I have tried so far
Playing around with Content Security Policy as mentioned here (but it's maybe more a Meteor / Cordova issue)
Splitting the message into chunks on application level (said here)
Sending some dummy acknowledgement bytes or disabling Nagle's algorithm (as suggested here)
Wrapping the onmessage callback into an
setTimeout()
(here)Protocols WS or WSS make no difference
Running the Autobahn Test Suite. Sometimes it passes all tests, sometimes some of them fail probably due to timeout or a too long execution time
Could someone maybe give me some hints or has experience with this kind of problems?
Update 02.02.017
Also worth to mention is that my application is a 3D application rendering in a loop via requestAnimationFrame.
After many days of research I found out there seems to be a problem regarding requestAnimationFrame + WebSockets onmessage handler.
I will update my findings tomorrow.