2009-07-13 34 views
2

我目前正在编写一个Comet应用程序,它需要我一次发送长时间连接的数据块。但是,在关闭连接之前,我无法将消息刷新到客户端。 PrintWriter.flush()方法的行为不像我认为的那样吗?Java Servlets:为什么PrintWriter.flush()不会冲洗?

这是我的Tomcat Comet实现:

public void event(CometEvent event) throws IOException, ServletException { 
    HttpServletRequest request = event.getHttpServletRequest(); 
    HttpServletResponse response = event.getHttpServletResponse(); 
    if (event.getEventType() == EventType.BEGIN) { 
     request.setAttribute("org.apache.tomcat.comet.timeout", 300 * 1000); 
     PrintWriter out = response.getWriter(); 
     out.println("BEGIN!"); 
     out.flush(); 
     System.out.println("EventType.BEGIN"); 
    } else if (event.getEventType() == EventType.READ) { 
     InputStream is = request.getInputStream(); 
     byte[] buf = new byte[512]; 
     do { 
      int n = is.read(buf); //can throw an IOException 
      if (n > 0) { 
       System.out.println("Read " + n + " bytes: " + new String(buf, 0, n) 
         + " for session: " + request.getSession(true).getId()); 
      } else if (n < 0) { 

       return; 
      } 
     } while (is.available() > 0); 
     System.out.println("subtype: "+event.getEventSubType()); 
     System.out.println("EventType.READ"); 
    } else if (event.getEventType() == EventType.END) { 
     PrintWriter out = response.getWriter(); 
     out.println("END!"); 
     out.close(); 
     System.out.println("checkError: "+out.checkError()); 
     System.out.println(event.getEventSubType()); 
     System.out.println("EventType.END"); 
     //eventWorker.enqueue(new EndEvent(request, response)); 
    } else if (event.getEventType() == EventType.ERROR) { 
     PrintWriter out = response.getWriter(); 

     out.println("ERROR!"); 
     out.flush(); 
     System.out.println("checkError: "+out.checkError()); 
     System.out.println("subtype: "+event.getEventSubType()); 

     //response.getWriter().close(); 
     System.out.println("EventType.ERROR"); 
    } else { 
     (new ServletException("EXCEPTION")).printStackTrace(); 
    } 
} 

所以在这里我想发送消息 “开始吧!”并保持连接后打开,所以我可以发送更多的数据。但是,在连接关闭之前,消息似乎没有通过。

这是我的ajax代码: $ .post('comet',function(data){alert(data);});

后,我运行此代码,萤火告诉我,这是响应头: 服务器:Apache-狼/ 1.1 传输编码:分块 日期:星期一,2009年21时十六分29秒GMT

7月13日

这使我认为我的浏览器收到了一些数据,但是如何在连接关闭之前更新页面上的某些内容?

回答

3

因此,浏览器似乎一直在接收数据,但由于连接未关闭,JavaScript思想数据仍在发送。这就是为什么我的jQuery回调函数没有被调用。

看看W3C AJAX教程,我注意到XMLHttpRequest对象有不同的就绪状态。

var xmlhttp; 
    if (window.XMLHttpRequest) 
     { 
     // code for IE7+, Firefox, Chrome, Opera, Safari 
     xmlhttp=new XMLHttpRequest(); 
     } 
    else if (window.ActiveXObject) 
     { 
     // code for IE6, IE5 
     xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); 
     } 
    else 
     { 
     alert("Your browser does not support XMLHTTP!"); 
     } 
    xmlhttp.onreadystatechange=function() 
    { 
     if(xmlhttp.readyState==3) { 
      alert('process '+xmlhttp.responseText); 
     } 
     if(xmlhttp.readyState==4) { 
      alert('ready '+xmlhttp.responseText); 
     } 
    } 
    xmlhttp.open("GET","comet",true); 
    xmlhttp.send(null); 

传统上,人们只处理第四个readyState,这意味着转移已完成。然而,就我而言,我需要在传输结束之前阅读数据。因此,我需要代码来处理第三个readyState。

0

我记得有一个servlet的问题,如果你的页面被重定向(就像一个错误页面),当前的响应缓冲区,在这种情况下,作家被扔掉而不被写入。

0

我并没有真正遵循这句话。

因此,一旦出现错误并且连接关闭,我会看到之前尝试发送的所有消息。

这是什么意思?此外,你可能想看看可用的api()。我认为它不符合你的想法。

+0

所以我在这里试图发送消息“BEGIN!”并保持连接后打开,所以我可以发送更多的数据。但是,在连接关闭之前,消息似乎没有通过。 – jcee14 2009-07-14 14:25:05

0

我有几乎相同的问题:

这两个电话,什么都没有出去。

writer.flush(); 
writer.end(); 

当我试图除了上述两种做response.flushBuffer(),一个java.nio.charset.UnmappableCharacterException被抛出(下的JBoss 5.1)。然后我添加了一个response.setCharacterEncoding("UTF-8);并且问题消失了。

这可能与您的问题没有任何关系,但自从我在谷歌中发现您的帖子以来,我在这里为具有相同情况的人回答。