7

我已尝试写入响应,因为没有适当的断开回调:

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

}

但这似乎不是诀窍。当客户端断开连接时,写入和刷新缓冲区没有抛出异常

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

我在 Jetty 8 和 Tomcat 7 上都试过了,我看到了同样的行为。

有没有办法查明客户端是否收到了消息?我错过了什么吗?

4

2 回答 2

1

我认识到您正在寻找一种检测断开连接的正确方法,但对于那些不介意杂乱无章的人:

注意:此方法会定期向客户端发送空格字符,在解释结果之前必须对其进行修剪。这是笨拙的部分。

  1. 启动一个可以访问 servlet 响应的 writer/outputstream 的线程。该线程定期(我使用 1 秒间隔)向客户端发送空格字符。包装在设置您的中止标志的 IOException try/catch 块中。

  2. 如果连接关闭,大多数 servlet 将在数据无法传送到客户端时抛出 EOFException(这是一个 IOException)。您正在捕获此异常并设置中止标志。

  3. 当中止标志被捕获时,您可以选择。您可以核对正在执行的线程,让您的所有处理定期检查中止标志,将异常推送到正在执行的线程中,或者执行任意数量的操作(此处未详细说明)。

  4. 如果该过程成功完成,您将获得以多个空格为前缀的结果。同样,请记住在您的客户端上修剪这些。

于 2015-07-22T18:16:15.287 回答
0

根据我的经验,当客户端与 servlet 断开连接时,会出现一个异常,指的是 Broken Pipe。

例如:在 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)
于 2013-04-08T12:47:31.500 回答