Jetty servlet 未检测到客户端已断开连接

Posted

技术标签:

【中文标题】Jetty servlet 未检测到客户端已断开连接【英文标题】:Jetty servlet does not detect that client has disconnected 【发布时间】:2011-07-08 16:54:12 【问题描述】:

这是我部署到 Jetty 的 servlet 的代码:

public class StreamServlet extends HttpServlet

  public void doGet( HttpServletRequest request, 
    HttpServletResponse response ) throws ServletException, IOException
  
    response.setContentType( "text/xml; charset=UTF-8" );
    response.setCharacterEncoding( "UTF-8" );

    InputStream is = this.getServletContext().getResourceAsStream( "A.xml" );
    BufferedReader reader = new BufferedReader( 
        new InputStreamReader( is, Charset.forName("UTF-8") ) );

    String line = "";
    try
    
      while( (line = reader.readLine()) != null ) 
        getServletContext().log( line );
        writer.println( line );
        writer.flush();
        Thread.sleep( 1500 ); // for testing
      
    
    catch (InterruptedException e)
    
        getServletContext().log("exception",e);
    
  

然后我在命令行上运行

curl -i http://localhost:8080/foo/servlet

文件A.xml 包含大约13,000 行;所以 curl 正确显示了它在 1.5 秒后收到的每一行。然后我中断了 curl,但令我惊讶的是 servlet 继续运行;即在这个while循环中。

while( (line = reader.readLine()) != null ) 
  getServletContext().log( line );
  writer.println( line );
  writer.flush();
  Thread.sleep( 1500 ); // for testing

为什么它会表现出这种行为?我没有使用延续。我正在运行 Jetty 6.1.26。我想要的是:当 servlet 线程检测到客户端已终止 http 连接时,它应该停止。

【问题讨论】:

【参考方案1】:

我不知道你从哪里得到作者,所以我假设它来自 response.getWriter()。

我认为可能发生的情况是 Jetty 在将响应发送到客户端之前在内部对其进行缓冲。它需要这样做,因为它需要计算响应的大小,以便它可以在 HTTP 响应标头中设置“Content-Length”字段。这是客户端需要的,因此它知道要阅读多少。 (嗯,这不是真的需要,但这是另一个讨论。)

我认为 Jetty 在您关闭编写器之前实际上不会发送数据。我还认为 flush() 没有做任何事情,因为它无法发送任何数据,直到它知道没有更多数据即将到来。当您写入此缓冲流时,它不会检查连接是否仍处于活动状态。

在你的循环中试试这个:

for(String line = reader.readLine(); line != null && !writer.checkError(); line = reader.readLine()) 
  getServletContext().log( line );
  writer.println( line );
  writer.flush();
  Thread.sleep( 1500 ); // for testing

我在想也许 writer.checkError() 会传播到实际的套接字输出流并检查它是否仍然打开。

编辑 1:嗯,没关系,我错过了你所说的 flush() 正在向 curl 发送数据的地方。不过,请尝试循环中的 checkError() 并告诉我它是否有效。

【讨论】:

【参考方案2】:

您不应该期待 IOException,而不仅仅是 InterruptedException 吗? 当客户端断开连接并且服务器尝试写入时,您将收到 IOException。不是吗? (不过,InterruptedException 处理 Thread.sleep 部分)。

【讨论】:

以上是关于Jetty servlet 未检测到客户端已断开连接的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 websocket 客户端未检测到意外的服务器断开连接

如何用C语言检测网络是不是连接上、已连接、已断开状态

Heroku 上的 Sinatra/Thin 未检测到 HTTP 流连接 (SSE) 客户端断开连接

xshell避免长时间未操作断开连接

远程桌面连接已断开 客户端无法连接。您已连接到这台计算机的控制台。无法建立新的控制台会话。

Jetty如何检测HTTP连接是不是被客户端关闭