as an addendum, the END event that you were seeing was caused by an EOF being sent from your test client to the server.

Filip

Peter Warren wrote:
Just to make sure that I wasn't crazy, I did some more tests,
including using your cometgui.jar.  My results still show both read
errors and END events.  Is it possible that it's a platform issue?
I'm running Windows XP Pro SP2.  As I mentioned before I'm using the
tomcat 6.0.x trunk as of 21-01-2008.  Also, I re-started tomcat in
between all tests to make sure there weren't stray bytes hanging
around somewhere.  My server code is the same as shown previously in
this thread.

Peter

Here are my results:

1) Running LastChunkTest (code below) with last chunk of 0crlfcrlf,
server shows:

event: BEGIN, subtype: null
event: READ, subtype: null
Read 10 bytes: comet test for session: 627378C9DEE2817A93EBAC190DE47599
read error

2) Running LastChunkTest with last chunk of 0crlfcrlf and a 50 ms
sleep before sending last chunk, server shows:

event: BEGIN, subtype: null
event: READ, subtype: null
Read 10 bytes: comet test for session: A00EFFC9A9FE8CBF1833D204EF00667C
event: END, subtype: null

3) Running LastChunkTest with a last chunk of 0crlf, server shows:

event: BEGIN, subtype: null
event: READ, subtype: null
Read 10 bytes: comet test for session: DD41C198E3D5CD6E7D73FC0D7B37E86F

4) Running cometgui.jar with 0crlfcrlf:

client sends (without the dashes):
---
GET /CometTest HTTP/1.1
User-Agent: Filips Awesome Client/1.0
Host: 127.0.0.1:8080
Transfer-Encoding: chunked

10
test data test 1
0

---

server shows:
event: BEGIN, subtype: null
event: READ, subtype: null
Read 16 bytes: test data test 1 for session: 4023C27063C5674C1F37D315C3AF0AFC
read error

5) Running cometgui.jar with 0crlf:

client sends (without the dashes):
---
GET /CometTest HTTP/1.1
User-Agent: Filips Awesome Client/1.0
Host: 127.0.0.1:8080
Transfer-Encoding: chunked

10
test data test 1
0
---

server shows:
event: BEGIN, subtype: null
event: READ, subtype: null
Read 16 bytes: test data test 1 for session: BC5EA8DA373D1E6726020F44F71165C7

side note: Not sure if this is important, but when doing the following
steps in cometgui for the client data shown above, I get the exception
below:
connect
submit
disconnect

Jan 22, 2008 10:42:49 AM org.apache.catalina.core.StandardWrapperValve event
SEVERE: Servlet.service() for servlet CometTest threw exception
java.io.EOFException: Unexpected EOF read on the socket
        at org.apache.coyote.http11.InternalNioInputBuffer.readSocket(InternalNi
oInputBuffer.java:589)
        at org.apache.coyote.http11.InternalNioInputBuffer.fill(InternalNioInput
Buffer.java:868)
        at org.apache.coyote.http11.InternalNioInputBuffer$SocketInputBuffer.doR
ead(InternalNioInputBuffer.java:892)
        at org.apache.coyote.http11.filters.ChunkedInputFilter.readBytes(Chunked
InputFilter.java:243)
        at org.apache.coyote.http11.filters.ChunkedInputFilter.parseCRLF(Chunked
InputFilter.java:326)
        at org.apache.coyote.http11.filters.ChunkedInputFilter.parseEndChunk(Chu
nkedInputFilter.java:356)
        at org.apache.coyote.http11.filters.ChunkedInputFilter.doRead(ChunkedInp
utFilter.java:136)
        at org.apache.coyote.http11.InternalNioInputBuffer.doRead(InternalNioInp
utBuffer.java:830)
        at org.apache.coyote.Request.doRead(Request.java:428)
        at org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.j
ava:298)
        at org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:405)
        at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:313)
        at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStrea
m.java:162)
        at com.seekspeak.server.debug.CometTestServlet.event(CometTestServlet.ja
va:31)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilterEvent
(ApplicationFilterChain.java:470)
        at org.apache.catalina.core.ApplicationFilterChain.doFilterEvent(Applica
tionFilterChain.java:363)
        at org.apache.catalina.core.StandardWrapperValve.event(StandardWrapperVa
lve.java:422)
        at org.apache.catalina.core.StandardContextValve.event(StandardContextVa
lve.java:252)
        at org.apache.catalina.core.StandardHostValve.event(StandardHostValve.ja
va:179)
        at org.apache.catalina.valves.ValveBase.event(ValveBase.java:200)
        at org.apache.catalina.valves.ValveBase.event(ValveBase.java:200)
        at org.apache.catalina.core.StandardEngineValve.event(StandardEngineValv
e.java:128)
        at org.apache.catalina.connector.CoyoteAdapter.event(CoyoteAdapter.java:
198)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.jav
a:292)
        at org.apache.coyote.http11.Http11NioProcessor.process(Http11NioProcesso
r.java:876)
        at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.pr
ocess(Http11NioProtocol.java:719)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoin
t.java:2080)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExec
utor.java:885)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor
.java:907)
        at java.lang.Thread.run(Thread.java:619)
event: ERROR, subtype: null


Code for LastChunkTest:
=======================
package test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.NoRouteToHostException;
import java.net.Socket;
import java.net.URL;

public class LastChunkTest {

    private static final String ENCODING = "ISO-8859-1";

    private static final String DELIMITER = "\r\n";

    private URL url;

    private InputStream inputStream;

    private OutputStream outputStream;

    private Socket socket;

    public static void main(String[] args) throws Exception {
        LastChunkTest test = new LastChunkTest();
        test.test();
    }

    private void test() throws Exception {
        url = new URL("http://www.seekspeak.com/CometTest";);
        initConnection();
        sendHeaders();
        send("comet test");
        // uncomment sleep to get END event instead of read error
//        try {
//            Thread.sleep(50);
//        } catch (InterruptedException ie) {
//            // do nothing
//        }
        sendLastChunk();
        // block on read to keep app alive - server never sends response
        inputStream.read();
    }

    private void initConnection() throws IOException {
        int port = url.getPort();
        port = (port < 0) ? url.getDefaultPort() : port;
        try {
            socket = new Socket(url.getHost(), port);
            socket.setKeepAlive(true);
            inputStream = socket.getInputStream();
            outputStream = socket.getOutputStream();
        } catch (NoRouteToHostException nrthe) {
            System.out.println("host: " + url.getHost());
            nrthe.printStackTrace();
        }
    }

    private void sendHeaders() throws IOException {
        String path = url.getPath();
        StringBuffer outputBuffer = new StringBuffer();
        outputBuffer.append("POST " + path + " HTTP/1.1" + DELIMITER);
        outputBuffer.append("Host: " + url.getHost() + DELIMITER);
        outputBuffer.append("User-Agent: CometTest" + DELIMITER);
        outputBuffer.append("Connection: keep-alive" + DELIMITER);
        outputBuffer.append("Content-Type: text/plain" + DELIMITER);
        outputBuffer.append("Transfer-Encoding: chunked" + DELIMITER);
        outputBuffer.append(DELIMITER);
        byte[] outputBytes = outputBuffer.toString().getBytes(ENCODING);
        outputStream.write(outputBytes);
        outputStream.flush();
    }

    private void send(String chunkData) throws IOException {
        byte[] chunkBytes = chunkData.getBytes(ENCODING);
        String hexChunkLength = Integer.toHexString(chunkBytes.length);
        StringBuffer outputBuffer = new StringBuffer();
        outputBuffer.append(hexChunkLength);
        outputBuffer.append(DELIMITER);
        outputBuffer.append(chunkData);
        outputBuffer.append(DELIMITER);
        byte[] outputBytes = outputBuffer.toString().getBytes(ENCODING);
        outputStream.write(outputBytes);
        outputStream.flush();
    }

    private void sendLastChunk() throws IOException {
        byte[] outputBytes = new String("0" + DELIMITER).getBytes(ENCODING);
        outputStream.write(outputBytes);
        outputStream.flush();
    }
}


On Jan 22, 2008 9:07 AM, Filip Hanik - Dev Lists <[EMAIL PROTECTED]> wrote:
I still don't get the END event, however, thanks for pointing it out,
you did find a regression bug about the timeout

http://svn.apache.org/viewvc?view=rev&revision=614249

I've added the patch above to the proposal list for 6.0.x to fix the
timeout issue

Filip


Peter Warren wrote:
as I  mentioned, the "last chunk" doesn't generate an END event, I tried
it locally. of course against 6.0.x trunk.

I played around a bit because I was definitely getting an END event
and found: Sending 0crlf does not generate and END event.  However
sending 0crlfcrlf, which is what HttpURLConnection does, does generate
an END (or sometimes a read error - see below...)  Looking at the http
spec, it seems like 0crlfcrlf is actually the proper way to terminate
the chunk body:

       Chunked-Body   = *chunk
                        last-chunk
                        trailer
                        CRLF

       last-chunk     = 1*("0") [ chunk-extension ] CRLF

Am I reading that correctly?

Note about END and read error:
When running both the client and the server locally (i.e. little
latency), sending 0crlfcrlf would sometimes generate a read error
(i.e. inputStream.isAvailable() > 0 would be true and then number of
bytes read would be < 0) and sometimes an END event.

I tried with both sockets and HttpURLConnection and saw similar
behavior.  However when using HttpURLConnection I could add a delay of
50 millis. and guarantee that I always got an end event (see code
below).

I am using the latest 6.0.x trunk updated locally today.

Peter

CLIENT CODE
===========
        URL url = new URL("http://www.seekspeak.com/CometTest";);
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
        urlConn.setRequestMethod("POST");
        urlConn.setChunkedStreamingMode(-1); // use default chunk length
        urlConn.setReadTimeout(0);
        urlConn.setDoInput(true);
        urlConn.setDoOutput(true);
        urlConn.connect();
        PrintWriter out = new PrintWriter(urlConn.getOutputStream(), true);
        out.print("test");
        out.flush();
         try {
            // sleep to guarantee an END event - remove this sleep to
get read error
            Thread.sleep(50);
        } catch (InterruptedException ie) {
            // do nothing
        }
        urlConn.getInputStream();

COMET SERVLET CODE:
=============
    public void event(CometEvent cometEvent) throws IOException,
ServletException {
        System.out.println("event: " + cometEvent.getEventType() + ",
subtype: " + cometEvent.getEventSubType());
        if (cometEvent.getEventType() == CometEvent.EventType.ERROR) {
            cometEvent.close();
        } else if (cometEvent.getEventType() == CometEvent.EventType.END) {
            cometEvent.close();
        } else if (cometEvent.getEventType() == CometEvent.EventType.READ) {
            HttpServletRequest request = cometEvent.getHttpServletRequest();
            InputStream inputStream = request.getInputStream();
            byte[] buf = new byte[512];
            do {
                int n = inputStream.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) {
                    System.out.println("read error");
                    return;
                }
            } while (inputStream.available() > 0);
        }
    }

On Jan 21, 2008 11:53 AM, Filip Hanik - Dev Lists <[EMAIL PROTECTED]> wrote:

answers inline

Peter Warren wrote:

First off, thanks for your responses.  The contributors to this list
are extremely responsive, patient, and helpful, and I really
appreciate it!

Hmm, in your test case did you set the HttpURLConnection to use
chunked transfers (setChunkedStreamingMode(...))?  I find if I use
chunked transfers, the HttpURLConnection sends a "last chunk" message
upon reading input from the server, which generates a comet END event
on the server.  If I don't use chunked transfers, no END event is
generated because no "last chunk" is sent by the client.


as I  mentioned, the "last chunk" doesn't generate an END event, I tried
it locally. of course against 6.0.x trunk.

Which brings up an option I never considered: will a comet servlet
function properly with non-chunked transfer (i.e. no transfer-coding
header)?  It seems to.


yes, it can, just send a very large content-length header

Lastly, I'm still a little confused about requiring the comet event to
be closed on an END event.  Doesn't this mean that tomcat comet can't
handle pipelined requests?  If a client sends 2 pipelined requests, it
will send a "last chunk" to indicate the end of the first request.
This "last chunk" will generate an END event on the server, which then
requires the connection to be closed.  After the comet event is closed
the server cannot send a response to the client.


pipelined requests are not defined by the HTTP spec for POST methods,
only for GET
assuming the pipelining you are talking about is true pipelining :)
if you just mean, next request, then yes, tomcat handles that just fine,
and that is why you have to call event.close()

The END event docs indicate that pipelined request will generate an
END event: ...End will also be called when data is available and the
end of file is reached on the request input (this usually indicates
the client has pipelined a request).


depends on what you mean by pipeline, see above


Thanks,
Peter

On Jan 20, 2008 8:15 PM, Filip Hanik - Dev Lists <[EMAIL PROTECTED]> wrote:


now I get it. I just ran through a test case, and an END event was not
thrown just because there was an end chunk.
the response is very much still open at that point


Filip

Peter Warren wrote:


What java.net.HttpURLConnection has to do with Tomcat and comet is
that HttpURLConnection is Java's implementation of an http client and
will likely be used by people developing comet apps for Tomcat.  In my
case, I want to use it because I can't use raw sockets on my applet
client due to permission problems when trying to use sockets behind a
proxy.

I understand that asynchronous writes are possible, but they're not
when using HttpURLConnection because HttpURLConnection sends a "last
chunk" message when it's done with its request.  "Last chunk"
generates a comet end event, which then requires that the connection
to the client be closed.

I guess I don't understand why tomcat needs to close the connection
after an END event.  It seems to me that the "last chunk" message from
the client simply indicates that the client is done sending its
request.  Why does the server need to close the connection when the
client finishes its request?

Peter

On Jan 19, 2008 6:01 PM, Filip Hanik - Dev Lists <[EMAIL PROTECTED]> wrote:



I'm not sure what HttpURLConnection has to do with Tomcat or comet.
and yes, asynchronous writes are possible, just not after the END or
ERROR events have been issued

Filip


Peter Warren wrote:



Does that mean that HttpURLConnection cannot be used for comet
requests with asynchronous (i.e. delayed) responses?

It would seem so to me since HttpURLConnection always sends an END
message before reading from the server and since the server can no
longer write to the client after closing the comet event.  Am I
missing something?  Is there a way to write to the client after the
comet event is closed?

Would you consider it a bug that HttpURLConnection is implemented that way?

Peter

On Jan 18, 2008 9:21 PM, Filip Hanik - Dev Lists <[EMAIL PROTECTED]> wrote:




during end and error, you MUST close the Comet event

Filip


Peter Warren wrote:




What do I do to make the END event stop repeating?  I don't want to
close the CometEvent yet because the server is waiting for data to
send to the client.  If I don't close the comet event, the END event
repeats incessantly.

I'm using an unsigned applet as a comet client.  To accommodate
proxies, I've had to change my comet client to use HttpURLConnection
instead of Sockets.  (Accessing ProxySelector from an applet to create
a socket with a proxy generates an AccessControlException.)

HttpURLConnection unfortunately sends a 0crlf when its input stream is
retrieved for reading.  This generates a Comet END event.  Short of
closing the comet event, how can I make the server stop notifying me
of END events?  I can't close the comet event because I want to hold
onto the comet output stream for use later to send data to the client.

>From the comet docs:
EventType.END: End may be called to end the processing of the request.
Fields that have been initialized in the begin method should be reset.
After this event has been processed, the request and response objects,
as well as all their dependent objects will be recycled and used to
process other requests. End will also be called when data is available
and the end of file is reached on the request input (this usually
indicates the client has pipelined a request).

This seems to indicate that even if I could get the END event to go
away quietly, the comet event's output stream might no longer be
usable anyway.

It seems to me I have 3 options:
1) figure out how to make the comet END event stop repeating and hope
it's output stream still works
2) figure out how to keep HttpURLConnection from sending 0crlf (don't
know if that can be done)
2) use sockets with ProxySelector (which requires signing my applet
and getting users to grant it privileges)

Thanks,
Peter

---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]








---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]






---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]







---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]





---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]






---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]





---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]





---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to