Сервлеты Java: почему PrintWriter.flush () не сбрасывается? - PullRequest
2 голосов
/ 14 июля 2009

В настоящее время я пишу приложение 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();
    }
}

Так вот, я пытаюсь отправить сообщение "НАЧИНАЕТСЯ!" и оставьте соединение открытым, чтобы я мог отправить больше данных. Однако, кажется, что сообщение не проходит, пока соединение не будет закрыто.

Это мой код ajax: $ .post ('comet', function (data) {alert (data);});

После запуска этого кода Firebug сообщает мне, что это заголовок ответа: Сервер: Apache-Coyote / 1.1 Передача-кодировка: чанки Дата: понедельник, 13 июля 2009 21:16:29 GMT

Это заставляет меня думать, что мой браузер получил некоторые данные обратно, но как мне обновить что-то на странице до закрытия соединения?

Ответы [ 4 ]

3 голосов
/ 14 июля 2009

Таким образом, кажется, что браузер получал данные все это время, но поскольку соединение не было закрыто, думал, что данные 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-е состояние готовности, что означает, что передача завершена. В моем случае, однако, мне нужно было прочитать данные до окончания передачи. Следовательно, мне нужен был код для обработки 3-го readyState.

0 голосов
/ 08 августа 2009

У меня была почти такая же проблема:

Оба звонка и ничего не выходит.

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

Когда я попытался сделать response.flushBuffer() в дополнение к двум вышеупомянутым, был брошен java.nio.charset.UnmappableCharacterException (под jboss 5.1). Затем я добавил response.setCharacterEncoding("UTF-8);, и проблема исчезла.

Вероятно, это не имеет никакого отношения к вашей проблеме, но, поскольку я нашел ваше сообщение первым в Google, я отвечу здесь для людей, имеющих такую ​​же ситуацию.

0 голосов
/ 14 июля 2009

Я действительно не следую за изюминкой.

Таким образом, когда возникает ошибка и соединение закрывается, я вижу все сообщения, которые я пытался отправить ранее.

что это значит? Кроме того, вы можете проверить API для доступных (). Я не думаю, что он делает то, что вы думаете.

0 голосов
/ 14 июля 2009

Я помню, что была проблема с сервлетами, когда, если ваша страница перенаправлена ​​(как на страницу с ошибкой), текущий буфер ответа, в данном случае пишущий, выбрасывается без записи.

...