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: [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]