Can a http server detect that a client has cancell

2019-01-14 15:45发布

问题:

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...

回答1:

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.



回答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 ?).