我已尝试写入响应,因为没有正确的断开回调:
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;
}
}
但这似乎没有诀窍。当客户端断开连接时,写入并刷新缓冲区不会引发异常。
奇怪的是,第二次尝试写入输出流时(断开连接后),write会抛出异常。它看起来像你第一次写/刷它,一些内部状态被设置为错误,没有通知。
我已尝试过Jetty 8和Tomcat 7,我也看到了同样的行为。
是否有解决方案可以确定客户是否收到了该消息?我错过了什么吗?
答案 0 :(得分:1)
我知道您正在寻找一种检测断线的正确方法,但对于那些不介意使用kludge的人:
注意:此方法会在解释结果之前定期向客户端发送必须的空格字符。这是kludgey的一部分。
启动一个可以访问servlet响应的writer / outputstream的线程。该线程定期向客户端发送空格字符(我使用1秒间隔)。包含IOException try / catch块,用于设置中止标志。
如果连接已关闭,则当无法将数据传递到客户端时,大多数servlet都会抛出EOFException(这是一个IOException)。您正在捕获此异常并设置中止标志。
当捕获中止标志时,您有选项。你可以查看正在执行的线程,让你的所有处理周期性地检查中止标志,将异常推送到执行线程,或做任何事情(这里没有详述)。
如果流程成功完成,您的结果将以多个空格为前缀。再次,请记住在客户端修剪这些内容。
答案 1 :(得分:0)
根据我的经验,当客户端断开与servlet的连接时,会出现一个引用Broken Pipe的异常。
例如:Broken Pipe when writing bytes in 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)