Search code examples
androidwebsocketandroidasync-koush

Why is AndroidAsync disconnect time so long?


I'm using the AndroidAsync koush low level network protocol library. I am connecting to a server with WebSocket. I am able to connect, send/receive messages, and disconnect. My disconnect time is very long. Server does not detect the disconnect for on average 59 seconds.

In order to reproduce the problem, I connect WebSocket, authorize, and start pinging every 10 seconds. Then I turn on Airplane Mode and my network connection drops. At this time the setClosedCallback method is called. Here is how I am logging this message:

private WebSocket mConnection;

private WebSocketConnectCallback mSocketCallback = new WebSocketConnectCallback() {
    @Override
    public void onCompleted(Exception ex, WebSocket webSocket) {
    ...
            webSocket.setClosedCallback(new CompletedCallback() {
            @Override
            public void onCompleted(Exception ex) {
                Log.d("websocket", "WebSocket closed");
                if (ex != null && ex.getMessage() != null) {
                    Log.e("websocket", "WebSocket closed exception: " + ex.getMessage());
                }
                disconnect();
            }
        });
    }
};

private void disconnect() {
    mPingHandler.removeCallbacks(pingRunnable);
    if (mConnection != null) {
        mConnection.close();
        mConnection = null;
    }
}

This is the log message letting me know that WebSocket has closed:

WebSocket closed exception: recvfrom failed: ETIMEDOUT (Connection timed out)

However our server does not receive the disconnect message for about 59 seconds. Our server is using these libraries:

  • gevent==1.0
  • gevent-websocket==0.9.2
  • greenlet==0.4.2

Is there a way to speed this up on my end? Is there a socket level timeout somewhere that I can set to a lower value so that my server guys get the disconnect message faster?


Solution

  • Because AndroidAsync does not implement the closing handshake which is required by RFC 6455 (see this for details), your WebSocket server cannot detect disconnection in the context of WebSocket. So, the server has to wait for ETIMEDOUT in the context of TCP/IP to detect disconnection.

    Use a WebSocket library that complies with RFC 6455 and implements the closing handshake correctly.