28

My web app must process and serve a lot of data to display certain pages. Sometimes, the user closes or refreshes a page while the server is still busy processing it. This means the server will continue to process data for several minutes only to send it to a client who is no longer listening.

Is it possible to detect that the connection has been broken, and react to it?

In this particular project, we're using Django and NginX, or Apache. I assumed this is possible because the Django development server appears to react to cancelled requests by printing Broken Pipe exceptions. I'd love to have it raise an exception that my application code could catch. It appears JSP can do this. So can node.js here.

Alternatively, I could register an unload event handler on the page in question, have it do a synchronous XHR requesting that the previous request from this user be cancelled, and do some kind of inter-process communication to make it so. Perhaps if the slower data processing were handed to another process that I could more easily identify and kill, without killing the responding process...

Community
  • 1
  • 1
Nick Retallack
  • 17,432
  • 17
  • 85
  • 110

2 Answers2

19

While @Oded is correct that HTTP is stateless between requests, app servers can indeed detect when the underlying TCP/IP connection has broken for the request being processed. Why is this? Because TCP is a stateful protocol for reliable connections.

A common technique for .Net web apps processing a resource intensive request is to check Response.IsClientConnected (docs) before starting the resource intensive work. There is no point in wasting CPU cycles to send an expensive response to a client that isn't there anymore.

private void Page_Load(object sender, EventArgs e)
{
    // Check whether the browser remains
    // connected to the server.
    if (Response.IsClientConnected)
    {
        // If still connected, do work
        DoWork();
    }
    else
    {
        // If the browser is not connected
        // stop all response processing.
        Response.End();
    }
}

Please reply with your target app server stack so I can provide a more relevant example.

Regarding your 2nd alternative to use XHR to post client page unload events to the server, @Oded's comment about HTTP being stateless between requests is spot on. This is unlikely to work, especially in a farm with multiple servers.

Steve Jansen
  • 8,930
  • 2
  • 27
  • 33
-2

HTTP is stateless, hence the only way to detect a disconnected client is via timeouts.

See the answers to this SO question (Java Servlet : How to detect browser closing ?).

Community
  • 1
  • 1
Oded
  • 463,167
  • 92
  • 837
  • 979
  • 1
    It seems odd, since TCP should be able to do this. I guess some things are lost in the abstraction. – Nick Retallack Apr 16 '10 at 10:20
  • @Nick Retallack - TCP can do this, but the HTTP protocol is defined as stateless. This means that TCP will make sure a request or response will go through reliably, but that's it. – Oded Apr 16 '10 at 10:55
  • 1
    @Oded yes, but isn't it possible to see if a TCP connection is still being maintained? – Earlz Apr 16 '10 at 22:49
  • @Earlz - HTTP would close the TCP connection once the request/response is over, no? – Oded Apr 17 '10 at 05:35
  • 2
    This is not a satisfactory answer. It is clearly possible. The only difficulty is that most servers do not expose this information easily. They do know it though. They have to know it, or they could not operate. One way to get it is to log disconnects and have your application periodically check the log. – Nick Retallack Apr 19 '10 at 20:39