8

I am working on an HTML/Javascript running on mobile devices that is communicating with a Qt/C++ application running on a PC. Both the mobile device and the PC are on a local network. The communication between the HTML page (client) and the C++ app (server) is done using Websockets.

The HTML page is a remote control for the C++ application, so it is needed to have a low latency connection between the mobile device and the PC.

When using any non-Apple device as a client, data is sent to a rate between 60 to 120 frames/sec, which is totally acceptable. When using an Apple device, this rate falls to 3-4 frames/sec. I also checked ping times (Websocket implementation, not a ping command from command line). They are acceptable (1-5 ms) for Apple devices as long as the device is not transmitting data. Whenever it transmits data, this ping time raises to 200ms.

Looking from the Javascript side, the Apple devices always send data at a consistent rate of 60 frames/sec, as any other devices do. However, on the server side, only 3 to 4 of these 60 frames are received when the client is an Apple device.

Does anyone have any idea on what can be happening?

Here is my Javascript code :

<script language="javascript" type="text/javascript">

        var wsUri = document.URL.replace("http", "ws");
        var output;
        var websocket;


        function init()
        {
            output = document.getElementById("output");
            wsConnect();
        }

        function wsConnect()
        {
            console.log("Trying connection to " + wsUri);
            try
            {
                output = document.getElementById("output");
                websocket = new WebSocket(wsUri);
                websocket.onopen = function(evt)
                {
                        onOpen(evt)
                };
                websocket.onclose = function(evt)
                {
                        onClose(evt)
                };
                websocket.onmessage = function(evt)
                {
                        onMessage(evt)
                };
                websocket.onerror = function(evt)
                {
                        onError(evt)
                };
            }
            catch (e)
            {
                console.log("Exception " + e.toString());
            }
        }


        function onOpen(evt)
        {
            alert("Connected to " + wsUri);
        }

        function onClose(evt)
        {
            alert("Disconnected");
        }

        function onMessage(evt)
        {
            alert('Received message : ' + evt.data);
        }

        function onError(evt)
        {
            alert("Error : " + evt.toString());
        }

        function doSend(message)
        {
            websocket.send(message);
        }

        window.addEventListener("load", init, false);
</script>

Data is sent from Javascript side using dosend() function.

Kara
  • 6,115
  • 16
  • 50
  • 57
Mickaël C. Guimarães
  • 1,020
  • 2
  • 14
  • 32

2 Answers2

1

Few ideas and suggestions.

  • Check if the client's WebSocket protocol is supported by the server. This question and answer discuss a case where different protocol versions were an issue.
  • The WebSocket standard permits implementations to arbitrarily delay transmissions and perform fragmentation. Additionally, control frames, such as Ping, do not support fragmentation, but are permitted to be interjected. These permitted behavioral difference may be contributing to the difference in times.
  • Check if the bufferedAmount attribute on the WebSocket to determine if the WebSocket is buffering the data. If the bufferedAmount attribute is often zero, then data has been passed to the OS, which may be buffering it based on OS or socket configurations, such as Nagle.
  • This question and answer mentions resolving delays by having the server send acknowledgements for each message.
  • To get a deeper view into the interactions, it may be useful to perform a packet trace. This technical Q&A in the Mac Developer Library may provide some resources as to how to accomplish this.
Community
  • 1
  • 1
Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169
  • Thank you for the suggestions. 1. Regarding Websocket protocol version, my server only supports the last version (13) and discards any attempt to connect with an older version. I've checked again and the iPad is connection using protocol version 13, so the problem does not come from here. 2. None of the frames I receive indicates it has been fragmented (FIN bit always set). 3. Where do I check this attribute? Here is no such attribute on handshake. 4. Interesting. I'm already using TCP_NODELAY so this is not my case. Besides that, I'm counting packets and the missing ones simply never arrive. – Mickaël C. Guimarães Feb 01 '13 at 15:59
  • I'll have a look at the MacOs packet trace documentation. I'm also testing running my server on a Mac to see if iPad+Mac works any better... – Mickaël C. Guimarães Feb 01 '13 at 16:06
  • I just checked the options you stated. All of them require an external computer to catch packets from the iPad. I tried Wireshard and I can see that there is few data coming from the iPad, as my application gets. It would be more interesting to get packets directly from the iPad - Something seems to be happening in the iPad that doesn't let most of the Websocket frames to go through. I'm still with the same problem, but thank you for your time. – Mickaël C. Guimarães Feb 04 '13 at 13:23
  • I tested running the C++ application on a Mac. In this case, the iPad performs well (60 frames/s). But when talking to a PC, it still drops do 3 frames/s, independently of being Windows XP or Windows 7. Another idea? – Mickaël C. Guimarães Feb 08 '13 at 18:14
1

The best way to get some more insight is to use the AutobahnTestsuite. You can test both clients and servers with that suite and find out where problems are situated.

I have created QWebSockets, a Qt based websockets implementation, and used that on several occasions to create servers. Performance from Apple devices is excellent.

However, there seems to be a severe problem with Safari when it comes to large messages (see https://github.com/KurtPattyn/QWebSockets/wiki/Performance-Tests). Maybe that is the problem.

Kurt Pattyn
  • 2,758
  • 2
  • 30
  • 42