2011-03-04 15 views
5

Este es el código del servlet que desplegué en Jetty:embarcadero servlet no detecta que el cliente se ha desconectado

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

entonces me encontré en la línea de comandos

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

El archivo A.xml contiene alrededor de 13,000 líneas; para que curl se muestre correctamente en cada línea que recibió después de 1,5 segundos. Luego interrumpí curl, pero para mi sorpresa el servlet continuó funcionando; es decir, en este ciclo while.

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

¿Por qué tiene este comportamiento? No estoy usando continuaciones. Estoy ejecutando Jetty 6.1.26. Lo que quiero: el hilo del servlet debe detenerse cuando detecta que el cliente ha terminado la conexión http.

Respuesta

0

No veo de dónde sacas el escritor, así que supongo que es de response.getWriter().

Lo que creo que puede estar sucediendo es que Jetty amortigua la respuesta internamente antes de enviarla al cliente. Necesita hacer esto porque necesita calcular el tamaño de la respuesta para que pueda establecer el campo "Content-Length" en el encabezado de respuesta HTTP. Esto es necesario para el cliente, por lo que sabe cuánto leer. (Bueno, no es realmente necesario, pero eso es otra discusión.)

Creo que Jetty en realidad no envía los datos hasta que cierra el escritor. También estoy pensando que flush() no hace nada porque no puede enviar ningún dato hasta que sepa que no viene nada más. Y no está verificando si la conexión aún está activa mientras escribe en este flujo de almacenamiento intermedio.

Pruebe esto para su bucle:

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 
} 

estoy pensando que tal vez el writer.checkError() se propaga hasta el OutputStream toma real y comprueba si todavía está abierta.

Edit 1: Hmmm no importa, me perdí el bit donde dijiste que el flush() está enviando datos al curl. Aún así, pruebe checkError() en su ciclo y avíseme si eso funciona.

0

¿No debería esperar IOException, no solo InterruptedException? Obtendrá una excepción IOException cuando el cliente se desconecta y el servidor intenta escribir en él. ¿No es así? (InterruptedException maneja la parte Thread.sleep, sin embargo).

Cuestiones relacionadas