2009-07-13 59 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);並且問題消失了。

這可能與您的問題沒有任何關係,但自從我在谷歌中發現您的帖子以來,我在這裏爲具有相同情況的人回答。