Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly detect a client disconnect in servlet spec 3?

I have tried writing to the response, because there is no proper disconnect callback:

private boolean write(byte[] output, AsyncContext context) {
    try {
        OutputStream stream  = context.getResponse().getOutputStream();
        stream.write(output);
        stream.flush();
        return true;
    } catch (IOException ex) {
        //client disconnected
        log.error(ex);
        removeAsyncContext(context);
        return false;
    }

}

But this didn't seem to the trick. When the client is disconnected, writing and flushing the buffer did not throw an exception.

The weird thing is, the second time you try to write to the output stream (after the disconnect), the write does throw an exception. It looks like the first time you write/flush it,some internal state is set to error, without notifying.

I have tried on both Jetty 8 and Tomcat 7 and I see the same behavior.

Is there a solution to find out whether the message is received by the client? Am I missing something?

like image 897
OvdB Avatar asked Aug 19 '11 16:08

OvdB


1 Answers

I recognize you are looking for a proper way of detecting disconnects, but for those who don't mind a kludge:

Note: This method periodically sends space characters to the client that must be trimmed before interpreting the results. This is the kludgey part.

  1. Start a thread that has access to the writer/outputstream of the servlet response. This thread sends space characters periodically (I used 1 second intervals) to the client. Wrap in a IOException try/catch block that sets your abort flag.

  2. If the connection is closed, most servlets will throw a flavor of EOFException (which is an IOException) when data cannot be delivered to the client. You are catching this exception and setting your abort flag.

  3. When the abort flag is caught, you have options. You can nuke the executing thread, have all your processing periodically check for the abort flag, push an exception into the executing thread, or do any number of things (not detailed here).

  4. Should the process finish successfully, you will get your results prefixed by a number of spaces. Again, remember to trim these on your client.

like image 179
Lomilar Avatar answered Sep 27 '22 17:09

Lomilar