如何在servlet规范3中正确检测客户端断开连接?

Ovd*_*vdB 6 java client asynchronous disconnect servlet-3.0

我已经尝试写入响应,因为没有正确的断开回调:

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

但这似乎没有诀窍.当客户端断开连接时,写入和刷新缓冲区不会引发异常.

奇怪的是,第二次尝试写入输出流时(断开连接后),写入会引发异常.它看起来像你第一次写/刷它,一些内部状态被设置为错误,没有通知.

我试过Jetty 8和Tomcat 7,我看到了同样的行为.

是否有解决方案来确定客户是否收到了该消息?我错过了什么吗?

Men*_*los 0

根据我的经验,当客户端与 servlet 断开连接时,会出现一个涉及损坏管道的异常。

例如:在 ServletOutputStream 中写入字节时管道损坏

我建议捕获 java.net.SocketException 并查看异常详细信息以验证它是否是损坏的管道(作为起点):

Caused by: ClientAbortException:  java.net.SocketException: Broken pipe
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:358)
    at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:354)
    at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:381)
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:370)
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:89)
Run Code Online (Sandbox Code Playgroud)