tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Warren <pe...@nomad.org>
Subject Re: comet read event
Date Mon, 04 Jun 2007 18:08:09 GMT
Hi Filip,

Somehow I missed your response a while back.  Below are two test clients
and one comet servlet.  One client works, and the other doesn't.  I
found out the failing client doesn't work because HttpURLConnection
doesn't seem to allow writing to the output stream after the input
stream has been requested (or at least I haven't figured out how to
allow it).  On the other hand, Filip cautioned me against using the
client that works because it re-sends http headers with each request,
which could potentially get received as data by the comet servlet. 

So... is there a way for me to use a single HttpURLConnection and be
able to read and write multiple times on its input and output streams? 
I tried setting Transfer-Encoding to chunked, but couldn't get it to
make a difference.  I'd like to use HttpURLConnection instead of raw
sockets to avoid having to manually handle the headers, redirects,
proxies, etc.  I realize this question is more java api specific than
tomcat comet specific, but since many comet users might like to use
HttpURLConnection, I thought it was still relevant here.

Thanks for any help,
Peter

### CometTestClient1.java - this test hangs since 2nd output on
HttpURLConnection doesn't get sent ###

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;

public class CometTestClient1 {

    private HttpURLConnection urlConn;

    private PrintWriter out;

    private URL url = new URL("http://127.0.0.1/CometTest");

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

    public CometTestClient1() throws IOException {
        initConnection();
    }

    private void initConnection() throws IOException {
        urlConn = (HttpURLConnection) url.openConnection();
        urlConn.setDoInput(true);
        urlConn.setDoOutput(true);
        urlConn.connect();
        out = new PrintWriter(urlConn.getOutputStream());
    }

    public void test() throws IOException {
        out.println("test 1");
        out.flush();

        String line = read(urlConn.getInputStream());
        System.out.println(line);

        // next line never gets sent out -- presumably because the url
connection
        // doesn't allow output after getInputStream has been called
        out.println("test 2");
        out.flush();

        line = read(urlConn.getInputStream());
        System.out.println(line);

        out.close();
        urlConn.disconnect();
    }

    private String read(InputStream is) throws IOException {
        StringBuffer inputBuffer = new StringBuffer();
        byte[] buf = new byte[512];
        do {
            int n = is.read(buf); // can throw an IOException
            if (n > 0) {
                inputBuffer.append(new String(buf, 0, n));
            } else if (n < 0) {
                return ("read error");
            }
        } while (is.available() > 0);
        return inputBuffer.toString();
    }
}

### CometTestClient2.java - works but sends new http headers for each
client output ###

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;

public class CometTestClient2 {

    private HttpURLConnection urlConn;

    private PrintWriter out;

    private URL url = new URL("http://127.0.0.1/CometTest");

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

    public CometTestClient2() throws IOException {
        initConnection();
    }

    private void initConnection() throws IOException {
        urlConn = (HttpURLConnection) url.openConnection();
        urlConn.setDoInput(true);
        urlConn.setDoOutput(true);
        urlConn.connect();
        out = new PrintWriter(urlConn.getOutputStream());
    }

    public void test() throws IOException {
        out.println("test 1");
        out.flush();

        BufferedReader in = new BufferedReader(new
InputStreamReader(urlConn.getInputStream()));

        String line = in.readLine();
        System.out.println(line);

        initConnection();
        out.println("test 2");
        out.flush();

        in = new BufferedReader(new
InputStreamReader(urlConn.getInputStream()));

        line = in.readLine();
        System.out.println(line);

        out.close();
        urlConn.disconnect();
    }
}

### CometTestServlet ###

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;

public class CometTestServlet extends HttpServlet implements
CometProcessor {
    private static final long serialVersionUID = 5472498184127924791L;

    public void event(CometEvent cometEvent) throws IOException,
ServletException {
        HttpServletRequest request = cometEvent.getHttpServletRequest();
        HttpServletResponse response = cometEvent.getHttpServletResponse();
        // don't want timeout events
        cometEvent.setTimeout(1000000);
        if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) {
            log("Begin for session: " + request.getSession(true).getId());
            respond(request, response);
        } else if (cometEvent.getEventType() ==
CometEvent.EventType.ERROR) {
            log("Error for session: " + request.getSession(true).getId()
+ ", " + cometEvent.getEventSubType());
            cometEvent.close();
        } else if (cometEvent.getEventType() == CometEvent.EventType.END) {
            log("End for session: " + request.getSession(true).getId());
            cometEvent.close();
        } else if (cometEvent.getEventType() == CometEvent.EventType.READ) {
            log("Read for session: " + request.getSession(true).getId());
            respond(request, response);
        }
    }

    private void respond(HttpServletRequest request, HttpServletResponse
response) throws IOException {
        String clientMessage = read(request);
        if (clientMessage != null && clientMessage.length() > 0) {
            response.getWriter().println(clientMessage);
            response.getWriter().flush();
        }
    }

    private String read(HttpServletRequest request) throws IOException {
        InputStream is = request.getInputStream();
        StringBuffer inputBuffer = new StringBuffer();
        byte[] buf = new byte[512];
        do {
            int n = is.read(buf); // can throw an IOException
            if (n > 0) {
                inputBuffer.append(new String(buf, 0, n));
                log("Read " + n + " bytes: " + new String(buf, 0, n) + "
for session: "
                        + request.getSession(true).getId());
            } else if (n < 0) {
                log("comet read error");
            }
        } while (is.available() > 0);
        return inputBuffer.toString();
    }
}

Filip Hanik - Dev Lists wrote:
> why don't you make your test available, I'll run it through
>
> Filip
>
> Peter Warren wrote:
>> Yes, I'm using the NIO connector.  Here is the config line from my
>> server.xml:
>>
>>     <Connector port="80"
>> protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150"
>> connectionTimeout="20000" keepAliveTimeout="120000"
>> maxKeepAliveRequests="-1" acceptorThreadCount="2" redirectPort="8443" />
>>
>> Are there any other configuration options I need to set?
>>
>> Peter
>>
>> Filip Hanik - Dev Lists wrote:
>>  
>>> and you are using the APR or the NIO connector right?
>>>
>>> Filip
>>>
>>> Peter Warren wrote:
>>>    
>>>> Thanks for the suggestion.  I changed the comet test servlet to read
>>>> directly from the input stream as shown in the advanced io
>>>> example.  I'm
>>>> still seeing the same behavior.  No comet read event gets generated on
>>>> the server, only the begin event which contains the client's first
>>>> message.  The client then sends its second message and blocks waiting
>>>> for the server.  No events are generated on the server in response to
>>>> the client's second message.  Any other tips for me?
>>>>
>>>> Thanks,
>>>> Peter
>>>>
>>>> from the CometTestServlet:
>>>>
>>>>     public void event(CometEvent cometEvent) throws IOException,
>>>> ServletException {
>>>>     ...
>>>>         if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) {
>>>>             log("Begin for session: " +
>>>> request.getSession(true).getId());
>>>>             String clientMessage = read(request);
>>>>             if (clientMessage != null && clientMessage.length() >
0) {
>>>>                 response.getWriter().println(clientMessage);
>>>>                 response.getWriter().flush();
>>>>             }
>>>>         }
>>>>     ...
>>>>
>>>>     private String read(HttpServletRequest request) throws
>>>> IOException {
>>>>         InputStream is = request.getInputStream();
>>>>         StringBuffer inputBuffer = new StringBuffer();
>>>>         byte[] buf = new byte[512];
>>>>         do {
>>>>             int n = is.read(buf); // can throw an IOException
>>>>             if (n > 0) {
>>>>                 inputBuffer.append(new String(buf, 0, n));
>>>>                 log("Read " + n + " bytes: " + new String(buf, 0,
>>>> n) + "
>>>> for session: "
>>>>                         + request.getSession(true).getId());
>>>>             } else if (n < 0) {
>>>>                 log("comet read error");
>>>>             }
>>>>         } while (is.available() > 0);
>>>>         return inputBuffer.toString();
>>>>     }
>>>>
>>>> from the CometTestClient:
>>>>
>>>>     public void test() throws IOException {
>>>>         out.println("test 1");
>>>>         out.flush();
>>>>
>>>>         String line = read(urlConn.getInputStream());
>>>>         System.out.println(line);
>>>>
>>>>         out.println("test 2");
>>>>         out.flush();
>>>>
>>>>         line = read(urlConn.getInputStream());
>>>>         System.out.println(line);
>>>>
>>>>         out.close();
>>>>         urlConn.disconnect();
>>>>     }
>>>>
>>>>     private String read(InputStream is) throws IOException {
>>>>         StringBuffer inputBuffer = new StringBuffer();
>>>>         byte[] buf = new byte[512];
>>>>         do {
>>>>             int n = is.read(buf); // can throw an IOException
>>>>             if (n > 0) {
>>>>                 inputBuffer.append(new String(buf, 0, n));
>>>>             } else if (n < 0) {
>>>>                 return ("read error");
>>>>             }
>>>>         } while (is.available() > 0);
>>>>         return inputBuffer.toString();
>>>>     }
>>>>
>>>> Filip Hanik - Dev Lists wrote:
>>>>  
>>>>      
>>>>> take a look at the documentation, the way you are reading it is
>>>>> incorrect.
>>>>> you need to take advantage of the available() method
>>>>>
>>>>> Filip
>>>>>
>>>>> Peter Warren wrote:
>>>>>           
>>>>>> My BEGIN block in my comet servlet now looks like the code below
>>>>>> (added
>>>>>> a while loop to read until the buffer is empty).  Is that what
>>>>>> you had
>>>>>> in mind?  The buffer in the BEGIN event only contains the client's
>>>>>> first
>>>>>> message.  Am I not emptying the buffer correctly?  Although, I
>>>>>> wouldn't
>>>>>> expect the buffer to contain the client's second message since the
>>>>>> client blocks for an ack from the server before sending its second
>>>>>> message.  Any other thoughts on what happens to the client's second
>>>>>> message and why no READ event is generated?
>>>>>>
>>>>>> Thanks for your help,
>>>>>> Peter
>>>>>>
>>>>>>         if (cometEvent.getEventType() ==
>>>>>> CometEvent.EventType.BEGIN) {
>>>>>>             log("Begin for session: " +
>>>>>> request.getSession(true).getId());
>>>>>>             BufferedReader reader =
>>>>>> cometEvent.getHttpServletRequest().getReader();
>>>>>>             String line = null;
>>>>>>             while ((line = reader.readLine()) != null) {
>>>>>>                 log("servlet received: " + line);
>>>>>>             
>>>>>> cometEvent.getHttpServletResponse().getWriter().println("servlet
>>>>>> received: " + line);
>>>>>>               
>>>>>> cometEvent.getHttpServletResponse().getWriter().flush();
>>>>>>             }
>>>>>>         }
>>>>>>
>>>>>>  
>>>>>>               
>>>>>>> Filip Hanik wrote:
>>>>>>>
>>>>>>> it could be because the data from the request already came in
with
>>>>>>> the
>>>>>>>                         
>>>>>> request.
>>>>>>  
>>>>>>               
>>>>>>> when the BEGIN happens, perform the actions as if there was a
>>>>>>> READ as
>>>>>>>                         
>>>>>> well, ie, empty out the buffer.
>>>>>>  
>>>>>>               
>>>>>>> Filip
>>>>>>>                         
>>>>>> Peter Warren wrote:
>>>>>>  
>>>>>>               
>>>>>>> The following client code generates a comet BEGIN event on the
>>>>>>> server
>>>>>>> but not a subsequent READ event, as I was expecting.  How come?
>>>>>>> Is my
>>>>>>> code wrong?  Are my expectations wrong?  See sequence of events
>>>>>>> commented in code below.
>>>>>>>
>>>>>>>     // client test method that sends messages to server and
>>>>>>> listens for
>>>>>>> responses
>>>>>>>     public void test() throws IOException {
>>>>>>>         out.println("test 1");
>>>>>>>         out.flush();
>>>>>>>
>>>>>>>         // server receives client's message, generates a BEGIN
>>>>>>> event,
>>>>>>> and sends response to client
>>>>>>>
>>>>>>>         in = new BufferedReader(new
>>>>>>> InputStreamReader(urlConn.getInputStream()));
>>>>>>>         System.out.println(in.readLine());
>>>>>>>
>>>>>>>         // client receives server's response and prints it
>>>>>>>
>>>>>>>         out.println("test 2");
>>>>>>>         out.flush();
>>>>>>>
>>>>>>>         System.out.println(in.readLine());
>>>>>>>
>>>>>>>         // client code blocks here waiting for server response.
>>>>>>>         // server never generates a READ event.  How come?
>>>>>>>         // Does the HttpURLConnection (see full code below) need
>>>>>>> to be
>>>>>>> set up differently?
>>>>>>>         // Am I using the PrintWriter incorrectly when sending
>>>>>>> to the
>>>>>>> comet servlet?
>>>>>>>
>>>>>>>         out.close();
>>>>>>>         urlConn.disconnect();
>>>>>>>     }
>>>>>>>
>>>>>>> Thanks for any help,
>>>>>>> Peter
>>>>>>>
>>>>>>> -- system --
>>>>>>>
>>>>>>> using:
>>>>>>> tomcat 6.0.13 on windows xp sp 2
>>>>>>> java 1.6.0_01
>>>>>>>
>>>>>>> -- test client & comet servlet source below --
>>>>>>>
>>>>>>> ## begin test client ##
>>>>>>>
>>>>>>> import java.io.BufferedReader;
>>>>>>> import java.io.IOException;
>>>>>>> import java.io.InputStreamReader;
>>>>>>> import java.io.PrintWriter;
>>>>>>> import java.net.HttpURLConnection;
>>>>>>> import java.net.URL;
>>>>>>>
>>>>>>> public class CometTestClient {
>>>>>>>
>>>>>>>     private HttpURLConnection urlConn;
>>>>>>>
>>>>>>>     private PrintWriter out;
>>>>>>>
>>>>>>>     private BufferedReader in;
>>>>>>>
>>>>>>>     public static void main(String[] args) throws Exception {
>>>>>>>         CometTestClient test = new CometTestClient();
>>>>>>>         test.test();
>>>>>>>     }
>>>>>>>
>>>>>>>     public CometTestClient() throws IOException {
>>>>>>>         initConnection();
>>>>>>>     }
>>>>>>>
>>>>>>>     private void initConnection() throws IOException {
>>>>>>>         URL url = new URL("http://127.0.0.1/CometTest");
>>>>>>>         urlConn = (HttpURLConnection) url.openConnection();
>>>>>>>         urlConn.setDoInput(true);
>>>>>>>         urlConn.setDoOutput(true);
>>>>>>>         urlConn.connect();
>>>>>>>         out = new PrintWriter(urlConn.getOutputStream());
>>>>>>>     }
>>>>>>>
>>>>>>>     public void test() throws IOException {
>>>>>>>         out.println("test 1");
>>>>>>>         out.flush();
>>>>>>>
>>>>>>>         in = new BufferedReader(new
>>>>>>> InputStreamReader(urlConn.getInputStream()));
>>>>>>>         System.out.println(in.readLine());
>>>>>>>
>>>>>>>         out.println("test 2");
>>>>>>>         out.flush();
>>>>>>>
>>>>>>>         System.out.println(in.readLine());
>>>>>>>
>>>>>>>         out.close();
>>>>>>>         urlConn.disconnect();
>>>>>>>     }
>>>>>>> }
>>>>>>>
>>>>>>> ## end test client ##
>>>>>>>
>>>>>>> ## begin comet servlet ##
>>>>>>>
>>>>>>> import java.io.BufferedReader;
>>>>>>> import java.io.IOException;
>>>>>>>
>>>>>>> import javax.servlet.ServletException;
>>>>>>> import javax.servlet.http.HttpServlet;
>>>>>>> import javax.servlet.http.HttpServletRequest;
>>>>>>>
>>>>>>> import org.apache.catalina.CometEvent;
>>>>>>> import org.apache.catalina.CometProcessor;
>>>>>>>
>>>>>>> public class CometTestServlet extends HttpServlet implements
>>>>>>> CometProcessor {
>>>>>>>     private static final long serialVersionUID =
>>>>>>> 5472498184127924791L;
>>>>>>>
>>>>>>>     public void event(CometEvent cometEvent) throws IOException,
>>>>>>> ServletException {
>>>>>>>         HttpServletRequest request =
>>>>>>> cometEvent.getHttpServletRequest();
>>>>>>>         // don't want timeout events
>>>>>>>         cometEvent.setTimeout(1000000);
>>>>>>>         if (cometEvent.getEventType() ==
>>>>>>> CometEvent.EventType.BEGIN) {
>>>>>>>             log("Begin for session: " +
>>>>>>> request.getSession(true).getId());
>>>>>>>             BufferedReader reader =
>>>>>>> cometEvent.getHttpServletRequest().getReader();
>>>>>>>             String line = reader.readLine();
>>>>>>>             if (line != null) {
>>>>>>>                 log("servlet received: " + line);
>>>>>>>            
>>>>>>> cometEvent.getHttpServletResponse().getWriter().println("servlet
>>>>>>> received: " + line);
>>>>>>>              
>>>>>>> cometEvent.getHttpServletResponse().getWriter().flush();
>>>>>>>             } else {
>>>>>>>                 cometEvent.close();
>>>>>>>             }
>>>>>>>         } else if (cometEvent.getEventType() ==
>>>>>>> CometEvent.EventType.ERROR) {
>>>>>>>             log("Error for session: " +
>>>>>>> request.getSession(true).getId()
>>>>>>> + ", " + cometEvent.getEventSubType());
>>>>>>>             cometEvent.close();
>>>>>>>         } else if (cometEvent.getEventType() ==
>>>>>>> CometEvent.EventType.END) {
>>>>>>>             log("End for session: " +
>>>>>>> request.getSession(true).getId());
>>>>>>>             cometEvent.close();
>>>>>>>         } else if (cometEvent.getEventType() ==
>>>>>>> CometEvent.EventType.READ) {
>>>>>>>             log("Read for session: " +
>>>>>>> request.getSession(true).getId());
>>>>>>>             BufferedReader reader =
>>>>>>> cometEvent.getHttpServletRequest().getReader();
>>>>>>>             String line = reader.readLine();
>>>>>>>             if (line != null) {
>>>>>>>            
>>>>>>> cometEvent.getHttpServletResponse().getWriter().println("servlet
>>>>>>> received: " + line);
>>>>>>>             } else {
>>>>>>>                 cometEvent.close();
>>>>>>>             }
>>>>>>>         }
>>>>>>>     }
>>>>>>> }
>>>>>>>
>>>>>>> ## end comet servlet ##
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>>
>>>>>>> To start a new topic, e-mail: users@tomcat.apache.org
>>>>>>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>>>>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                           
>>>>>> ---------------------------------------------------------------------
>>>>>>
>>>>>> To start a new topic, e-mail: users@tomcat.apache.org
>>>>>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>>>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>>>>
>>>>>>
>>>>>>
>>>>>>                   
>>>>> ---------------------------------------------------------------------
>>>>> To start a new topic, e-mail: users@tomcat.apache.org
>>>>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>>>
>>>>>
>>>>>
>>>>>             
>>>> ---------------------------------------------------------------------
>>>> To start a new topic, e-mail: users@tomcat.apache.org
>>>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>>
>>>>
>>>>
>>>>         
>>> ---------------------------------------------------------------------
>>> To start a new topic, e-mail: users@tomcat.apache.org
>>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>
>>>
>>>
>>>     
>>
>> ---------------------------------------------------------------------
>> To start a new topic, e-mail: users@tomcat.apache.org
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>>
>>
>>
>>   
>
>
>
> ---------------------------------------------------------------------
> To start a new topic, e-mail: users@tomcat.apache.org
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>
>

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


Mime
View raw message