2

我目前正在编写一个 Comet 应用程序,它要求我在持久连接上一次发送大量数据。但是,在关闭连接之前,我无法将消息刷新到客户端。是否有任何原因 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();
    }
}

所以在这里我试图发送消息“BEGIN!” 并在之后保持连接打开,以便我可以发送更多数据。但是,似乎在连接关闭之前消息不会通过。

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

运行此代码后,Firebug 告诉我这是响应标头: Server: Apache-Coyote/1.1 Transfer-Encoding: chunked Date: Mon, 13 Jul 2009 21:16:29 GMT

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

4

4 回答 4

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

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

于 2009-07-14T15:36:29.253 回答
0

我记得 servlet 存在一个问题,如果您的页面被重定向(例如到错误页面),当前的响应缓冲区(在这种情况下为 writer)会被丢弃而不被写入。

于 2009-07-13T21:40:52.100 回答
0

我并没有真正遵循妙语。

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

这意味着什么?此外,您可能想查看可用()的 api。我不认为它做你认为它做的事。

于 2009-07-14T01:34:36.807 回答
0

我遇到了几乎同样的问题:

两个电话都没有出去。

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

当我尝试response.flushBuffer()在上述两个之外执行 ajava.nio.charset.UnmappableCharacterException时,抛出了 a(在 jboss 5.1 下)。然后我添加了一个response.setCharacterEncoding("UTF-8);,问题就消失了。

This has probably nothing to do with your problem but since I found your post as the first in google, I answer it here for people having the same situation.

于 2009-08-08T15:41:13.157 回答