tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Filip Hanik - Dev Lists <devli...@hanik.com>
Subject Re: comet read event
Date Mon, 04 Jun 2007 18:39:22 GMT
I doubt it works properly with the HttpUrlConnection, its better if you 
use a socket connection, as you have no idea how the underlying 
implementation works in HttpUrlConnection

Filip

Peter Warren wrote:
> 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
>
>
>
>   


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