node.jstcpwebsocketkeep-aliveqtwebsockets

Overhead of Idle WebSockets


Say I have an websocket that may receive an event at any time, but is mostly idle, how much bandwidth will be consumed after the initial connection in order to keep it alive?

For what it's worth, the server is NodeJS using ws, and the client is using QtWebSockets.

Thanks!


Solution

  • Once established (meaning the three-way handshake completes), a raw TCP connection uses zero bandwidth unless:

    A server or client can enable TCP keepalives. A keepalive is a zero-length packet sent with the ACK flag set, and is only 54 bytes sent on the wire plus another 54 for the response. By default, TCP keepalives are sent every two hours. In other words, completely negligible.

    WebSockets also have their own keepalive mechanism (to deal with proxies). The server or the client may send a PING frame, and the other end MUST respond with a PONG frame. While there is no browser-side JS API to send PINGs, a node server may send them and a compliant browser will automatically respond. (QtWebSockets does have an API to send PINGs.) This does not happen by default; you must do it manually. WebSocket PING and PONG frames are at least 7 bytes and at most 131 bytes each (plus 54 bytes of TCP/IP overhead). Thus a single PING/PONG costs between 122 and 370 bytes.

    ws does not do any keepalives automatically, nor does QtWebSockets. So to answer your question, a default configuration does use zero bandwidth to maintain the TCP connection.

    However...

    Keepalives are important because intermediate devices (ie NAT routers) will drop inactive TCP connections. Depending on the networks between your server and your clients, this means that if you don't have any keepalives, your clients will lose their connections (possibly without knowing it, which is bad), and will have to re-eastablish the WebSocket session. This will likely be far more expensive in terms of bandwidth than enabling sane keepalives.

    A PING/PONG every 5 minutes costs 1.5 - 4.4 kB per hour (per client).


    Note: socket.io has its own keepalive mechanism (separate from WebSockets') that is enabled by default. The sio keepalive is managed by the sio library and happens over the WebSocket data channel (as opposed to WebSocket PING/PONG, which are control frames). The socket.io server sends an 8 byte (+overhead) keepalive message every 30 seconds, which amounts to about 15 kB per hour.