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

时间:2011-03-04 09:45:57

标签: java servlets jetty

这是我部署到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连接时,它应该停止。

2 个答案:

答案 0 :(得分:0)

我看不到你在哪里得到作家,所以我假设它来自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()传播到实际的socket输出流并检查它是否仍然打开。

编辑1:嗯,没关系,我错过了你说flush()正在发送数据卷曲的位置。仍然,尝试循环中的checkError(),让我知道这是否有效。

答案 1 :(得分:0)

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