Re: nio connector configuration
Sorry to bump this thread. I'm willing to pay for some assistance if anyone's interested in helping. I'm trying to figure out 2 problems when running my system under a light-moderate load test: 1) why do my comet timeout events not get generated on time (supposed to be every 50 seconds, averaging 56s, with many refused connections skewing the average down, max 85s)? 2) why is tomcat refusing connections under what seems to be a reasonable load? I'm happy to do more legwork on my own -- just looking for some pointers here. Can anyone help me out? Looking at JConsole, 2 items that look suspicious: 1) blocked http-acceptor threads, and 2) block-poller and client-poller threads that show a high number of blocks (see below). Also, the non-comet http requests are returning quickly, averaging ~150ms, so it seems to be only my comet requests that are having issues. Running a load test with 600 total client threads averaging 14 requests/sec. 300 threads making normal http requests, 300 threads making comet requests that wait 50 seconds for a server timeout. Tomcat 6.0.18 on Windows XP. Connector port=80 protocol=org.apache.coyote.http11.Http11NioProtocol maxThreads=1000 acceptorThreadCount=5 acceptorThreadPriority=10 pollerThreadCount=5 pollerThreadPriority=10 redirectPort=8443 enableLookups=false / after 1/2 hour running: normal http requests: 2 samples, averaging 150 ms, ~.5% error comet requests: 1 samples, averaging 56s, ~3.5% error Information from JConsole: CPU avg: 5-10% threads: stable @ ~300 memory: stable @ ~130MB Thread status from JConsole of the http-acceptor, block-poller, and client-poller threads: Name: http-80-Acceptor-0 State: BLOCKED on java.lang.obj...@17a82f1 owned by: http-80-Acceptor-4 Total blocked: 132 Total waited: 0 Stack trace: sun.nio.ch.ServerSocketChannelImpl.accept(Unknown Source) org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:1198) java.lang.Thread.run(Unknown Source) - Name: http-80-Acceptor-1 State: BLOCKED on java.lang.obj...@17a82f1 owned by: http-80-Acceptor-4 Total blocked: 129 Total waited: 0 Stack trace: sun.nio.ch.ServerSocketChannelImpl.accept(Unknown Source) org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:1198) java.lang.Thread.run(Unknown Source) - Name: http-80-Acceptor-2 State: BLOCKED on java.lang.obj...@17a82f1 owned by: http-80-Acceptor-4 Total blocked: 122 Total waited: 0 Stack trace: sun.nio.ch.ServerSocketChannelImpl.accept(Unknown Source) org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:1198) java.lang.Thread.run(Unknown Source) - Name: http-80-Acceptor-3 State: BLOCKED on java.lang.obj...@17a82f1 owned by: http-80-Acceptor-0 Total blocked: 166 Total waited: 0 Stack trace: sun.nio.ch.ServerSocketChannelImpl.accept(Unknown Source) org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:1198) java.lang.Thread.run(Unknown Source) - Name: http-80-Acceptor-4 State: BLOCKED on java.lang.obj...@17a82f1 owned by: http-80-Acceptor-0 Total blocked: 133 Total waited: 0 Stack trace: sun.nio.ch.ServerSocketChannelImpl.accept(Unknown Source) org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:1198) java.lang.Thread.run(Unknown Source) - Name: http-80-ClientPoller State: RUNNABLE Total blocked: 17,950 Total waited: 5 Stack trace: sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method) sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(Unknown Source) sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(Unknown Source) sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source) sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source) - locked sun.nio.ch.uti...@f7b8fc - locked java.util.collections$unmodifiable...@195afdb - locked sun.nio.ch.windowsselectori...@c56236 sun.nio.ch.SelectorImpl.select(Unknown Source) org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:1473) java.lang.Thread.run(Unknown Source) - Name: NioBlockingSelector.BlockPoller-1 State: RUNNABLE Total blocked: 10,645 Total waited: 0 Stack trace: sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method) sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(Unknown Source) sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(Unknown Source) sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source) sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source) - locked sun.nio.ch.uti...@b2ee9a - locked java.util.collections$unmodifiable...@14eda77 - locked sun.nio.ch.windowsselectori...@1e8bb4c sun.nio.ch.SelectorImpl.select(Unknown Source) org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:305) Thanks for any help, Peter - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: nio connector configuration
I'm trying to figure out how best to configure nio so that my comet timeout events get generated in a timely manner. I have the comet events set to generate a timeout every 50 seconds. Works fine with few users. Under a moderate but reasonable load the timeout gets generated on average every 113 seconds. My configuration tweaks haven't yielded any noticeable changes (see below). Test results... Background: - using JMeter - 300 threads executing normal http requests, averaging ~9.8 requests/second. - 300 threads executing comet requests that simply wait for the server to close the connection every 50 seconds, averaging ~2.6 requests/second. - server is ubuntu 8.10 running tomcat 6.0.18. - server is not cpu constrained, averaging about 8-12% cpu - server doesn't seem to be memory constrained. top shows 80% of memory after hours of test (machine has 512MB physical memory and tomcat has a max heap set to 384MB) - network latency isn't a problem I ran 2 tests with different configurations for the nio connector: 1 test with bare-bones settings, and 1 test with everything that seemed like it might make a difference. Connector port=80 protocol=org.apache.coyote.http11.Http11NioProtocol redirectPort=8443 enableLookups=false / Ran for 3+ hours. 8-12% cpu. 12.4 requests/second. comet requests: average response time 112 secs, min 21 secs, max 179 secs Connector port=80 protocol=org.apache.coyote.http11.Http11NioProtocol maxThreads=1000 minSpareThreads=200 acceptorThreadCount=20 acceptorThreadPriority=10 pollerThreadCount=20 pollerThreadPriority=10 redirectPort=8443 enableLookups=false / Ran for 1 1/2 hours. 8-12% cpu. 12.2 requests/second. comet requests: average response time 113 secs, min 50 secs, max 133 secs So how can I get my comet timeouts generated at close to 50 secs under load? I thought maybe the poller thread priority was too low (does the poller thread generate the timeouts?), but setting its priority to max didn't change anything. Just to make sure I wasn't doing anything dumb in my client code, I replaced my event() method with the one below and still got the same disparity in comet timeouts, ranging from 50 to 120 secs: public void event(CometEvent event) throws IOException, ServletException { HttpServletRequest request = event.getHttpServletRequest(); if (event.getEventType() == CometEvent.EventType.BEGIN) { event.setTimeout(5); } else if (event.getEventType() == CometEvent.EventType.ERROR) { event.close(); } else if (event.getEventType() == CometEvent.EventType.END) { event.close(); } else if (event.getEventType() == CometEvent.EventType.READ) { InputStream is = request.getInputStream(); byte[] buf = new byte[512]; do { is.read(buf); // can throw an IOException } while (is.available() 0); } } I just checked the priority of the thread issuing the comet timeout event and its priority is 5. I have both the acceptor and poller thread priorities set to 10. How can I bump up the priority of the thread that issues the timeout events (in this case named http-80-exec-1)? Thanks for any ideas, Peter - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
comet end vs. client_disconnect
How do I distinguish between a comet END event generated due to a client disconnect and an end event generated for some other reason? I'm using tomcat 6.0.18 with the nio connector. On both windows xp sp3 and ubuntu 8.10, I'm seeing END events generated when a client disconnects and for other situations. I never receive error events with a subtype of CLIENT_DISCONNECT, which is what I was expecting when a client disconnects. In the aio docs, I read: 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). So END events get generated on a client disconnect but may also get generated for pipelined requests. So how can I tell definitively if a client disconnects? I also read: note: some of these events require usage of the org.apache.catalina.valves.CometConnectionManagerValve so I enabled the CometConnectionManagerValve, but still I don't receive error events with a CLIENT_DISCONNECT subtype. I've got stack traces for the 2 situations I encounter that generate end events. This partial stack is from a client disconnect that generates an END event: Http11NioProcessor.event(SocketStatus) line: 750 Http11NioProtocol$Http11ConnectionHandler.event(NioChannel, SocketStatus) line: 653 NioEndpoint$SocketProcessor.run() line: 2081 This partial stack is from something other than a client disconnect (maybe a pipelined request?) that generates an END event: Http11NioProcessor.process(NioChannel) line: 880 Http11NioProtocol$Http11ConnectionHandler.process(NioChannel) line: 719 NioEndpoint$SocketProcessor.run() line: 2081 Note that the traces diverge at NioEndpoint$SocketProcessor.run() line: 2081 due to the value of NioEndpoint$SocketProcessor.status, which is null in the second case. Is there a configuration issue that I can remedy to start receiving error events with subtype CLIENT_DISCONNECT? Barring that, is there some flag in the CometEvent or some object accessible from the CometEvent that I can use to tell if an END event was generated due to a client disconnect? Thanks, Peter - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: comet end vs. client_disconnect
CLIENT_DISCONNECT is only used a subtype of ERROR and that happens when the socket is closed from the client side When a client disconnects (i.e. socket is closed from the client side), I see an END event on both Windows and Ubuntu. I expected an ERROR event with a subtype of CLIENT_DISCONNECT, but I receive no ERROR events of any kind. Should I be receiving the ERROR event in addition to or instead of the END event? Peter - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
nio connector configuration
Looking for nio configuration tips for 6.0.18... I have an ajax app that uses a single socket connection for sending standard http requests and receiving responses, and another socket connection to listen via comet for messages pushed out by the server. A comet timeout is generated every 50 seconds, and the server then closes the client connection. The client immediately reconnects. This heartbeat lets me know the client is still alive. In load testing with JMeter, I find that when running somewhere between 100 200 threads (1/2 making regular http requests and 1/2 making comet listen requests that connect and then wait until the server closes the connection) the comet timeout events get generated more and more slowly. When they should be generated every 50 seconds, after only a little over a minute into the load test, the timeouts slow to sometimes over 60 seconds. When running 100 threads, the system works fine with the timeouts occurring less than every 60 seconds indefinitely. I'm not much of a tomcat administrator and am trying to figure out how to best to tune it for my app. This is what my connector config looks like now. Basically I'm throwing the kitchen sink at it, and then planning on fine-tuning it once I find something that makes a difference. Connector port=80 protocol=org.apache.coyote.http11.Http11NioProtocol maxThreads=1000 acceptCount=18192 acceptorThreadCount=2 acceptorThreadPriority=10 pollerThreadCount=2 pollerThreadPriority=10 maxKeepAliveRequests=-1 command-line-options=-Dorg.apache.tomcat.util.net.NioSelectorShared=false selectorPool.maxSelectors=500 redirectPort=8443 enableLookups=false / A couple notes: the acceptorThreadPriority and pollerThreadPriority are set using ints because I get the following warnings in the catalina log when trying to use the documented notation: WARNING: [SetAllPropertiesRule]{Server/Service/Connector} Setting property 'pollerThreadPriority' to 'java.lang.Thread#MAX_PRIORITY' did not find a matching property. I also get the warning when trying to use keepAliveTimeout. Is this property available for the nio connector? WARNING: [SetAllPropertiesRule]{Server/Service/Connector} Setting property 'keepAliveTimeout' to '12' did not find a matching property. I also get the warning when trying to use command-line-options, or am I supposed to really be setting this property on the command line? WARNING: [SetAllPropertiesRule]{Server/Service/Connector} Setting property 'command-line-options' to '-Dorg.apache.tomcat.util.net.NioSelectorShared=false' did not find a matching property. Thanks for any tips, Peter - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: nio connector configuration
Thanks for the tips. Very helpful. I also get the warning when trying to use keepAliveTimeout. Is this property available for the nio connector? No; it's only listed under the older connector (the one labeled Standard Implementation that then somewhat ambiguously refers to HTTP). I suspected as much, but got confused when I used the acceptCount property and tomcat didn't complain. acceptCount is only listed under the standard implementation as well, so I expected a warning. '-Dorg.apache.tomcat.util.net.NioSelectorShared=false' did not find a matching property. Works for me (at least I don't get any error message) on 6.0.18 running with JDK 6u12 on a Vista 64 box; how are you setting the above property, and what are your running on? I was setting it as a property in the connector config. Maybe that was silly of me, but I thought maybe all the properties were localized in the connector. I just tried it as a command-line option and it seemed to work. Interesting side note, with -Dorg.apache.tomcat.util.net.NioSelectorShared=false set and selectorPool.maxSelectors=500. My server code starts generating comet END events after about 30 threads start and only about 10 seconds into the test. Peter - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: comet loop after webapp re-start
Thanks for the pointer. That bug does look related, as does this one: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933 -- fixed against java 7. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
comet loop after webapp re-start
I'm running tomcat 6.0.18 on Ubuntu 8.10. I have a comet application that maintains an open connection with tomcat. If I re-start my webapp and then close the client connection, tomcat goes into a loop and chews up all cpu. This server is not live and only has my single client. The ClientPoller thread consumes most of the cpu running through the following stack over and over. Daemon Thread [http-80-ClientPoller] (Suspended (breakpoint at line 654 in ThreadPoolExecutor)) ThreadPoolExecutor.execute(Runnable) line: 654 NioEndpoint.processSocket(NioChannel, SocketStatus, boolean) line: 1161 NioEndpoint.processSocket(NioChannel, SocketStatus) line: 1148 NioEndpoint$Poller.processKey(SelectionKey, NioEndpoint$KeyAttachment) line: 1555 NioEndpoint$Poller.run() line: 1508 Thread.run() line: 619 This is not a problem with my CometProcessor not handling the comet events; the END event when the client connection is closed is never delivered to my CometProcessor, understandably since I just re-started the webapp and there is now a new CometProcessor instance. I believe what is happening is that the NIO connector is trying to deliver the END event to a CometProcessor that no longer exists and just keeps trying. Should the NIO connector recognize that the event is undeliverable and give up? Or is there something I need to do in webapp shutdown code to tell the NIO processor to disregard any open connections? The workaround is to always re-start the tomcat instead of just the webapp. This is possible for me since my server is only serving a single webapp. Peter - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: comet loop after webapp re-start
What JVM are you using? The stack trace doesn't look like anything that a HotSpot JVM would produce. It's Sun Java 1.6.0_10-b33. I grabbed the trace from my eclipse debugger. And I see the loop when running both with and without vm debug flags. Peter - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: comet end event
Could you indulge me and try the client with the sleep? I see the end event when there's a break/delay between sending a chunk and sending the last chunk. It is legal http to send the last chunk separately from preceding chunks, isn't it? getting a -1 on a inputstream.read is normal (even for a regular servlet). The read error indicates slightly more: that inputstream.isAvailable() is 0 and that inputstream.read() returns -1. Do I understand correctly in thinking that this -1 can indicate two different situations: 1) the client sent a last chunk; or 2) the client socket closed while the server was reading? If the above is true, it might be nice to have a way to disambiguate the two situations. Also, documentation-wise, it might be nice to comment the servlet code in http://tomcat.apache.org/tomcat-6.0-doc/aio.html to indicate that the -1 can occur on a last chunk as well as a read error. As a new comet user, I incorrectly took your sample code block (in the aio doc page) below to mean that a -1 always indicated some kind of error: } else if (n 0) { error(event, request, response); return; } 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]
Re: comet end event
Could you indulge me and try the client with the sleep? just did, worked exactly as before. event: BEGIN, subtype: null event: READ, subtype: null Read 10 bytes: comet test for session: A01334D0AC22505DCD4B323820963FEC read error event: ERROR, subtype: TIMEOUT Hmm, not sure where to go from here then. Here's my output: Jan 29, 2008 4:36:23 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 1173 ms event: BEGIN, subtype: null event: READ, subtype: null Read 10 bytes: comet test for session: CAF116EB9DF8BB1C5DD3170FC70F2394 event: END, subtype: null If you are unsure if you have messed up Tomcat binaries, then I would test this one http://people.apache.org/~fhanik/tomcat/tomcat-5.5/v5.5.26/bin/ I don't think it's bad binaries 'cause I've rebuilt a number of times, but I'm happy to give new binaries a try. You're pointing to tomcat 5.5 binaries though -- I thought comet was a 6.0 feature. Should I try the 5.5 binaries anyway? yes, we are very aware that the sample code is not the best for getting started, we are looking to replace it, but it takes time and resources. I didn't mean to be critical -- merely pointing out an area of confusion for me. In fact, I thought the sample code was reasonably sufficient for me to get up and running. My main issues were getting the client http chunking working properly. contributions always welcome! I'm pretty sure you don't want me writing the sample code! :) I'm still learning here, but I hope that our dialog is a contribution of sorts. As I mentioned before, my comet app is working fine using non-chunked httpurlconnections. This end event issue is not a roadblock for me -- I'm pursuing it to help tomcat and tomcat users, and satisfy my own curiosity of course. :) Hopefully others will learn from my misunderstandings, code snippets, etc. 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]
Re: comet end event
Is the read error expected behavior? I guess I didn't expect the comet processor to send me a read event on a last chunk since there's nothing to be read. I thought either a read error or an end event after a last chunk indicated a problem. If the read error is ok, then... Did you try the client with the 50 ms sleep? The client code has a commented block that says: uncomment sleep to get END event instead of read error. Adding the sleep generates the end event for me. Also, did you try with your cometgui client? As I mentioned, submitting a chunk and then separately submitting an end chunk generates an end event for me. If I send the two chunks together, I get the read error. Peter On Jan 28, 2008 1:37 PM, Filip Hanik - Dev Lists [EMAIL PROTECTED] wrote: works just dandy, the timeout happens after quite some time of just waiting Jan 28, 2008 2:33:31 PM org.apache.coyote.http11.Http11NioProtocol start INFO: Starting Coyote HTTP/1.1 on http-8080 Jan 28, 2008 2:33:31 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 1005 ms event: BEGIN, subtype: null event: READ, subtype: null Read 10 bytes: comet test for session: D4BC1A6D7AC7F30C1A475FB7FFB2B4DB read error event: ERROR, subtype: TIMEOUT If you are unsure if you have messed up Tomcat binaries, then I would test this one http://people.apache.org/~fhanik/tomcat/tomcat-5.5/v5.5.26/bin/ these are not an official version, but you can test it out and see how your test works Filip Peter Warren wrote: I put up a war file at: http://www.nomad.org/comet_test.war. It includes the webapp, source for the comet servlet client, and the server.xml file. Let me know if I missed anything. As I mentioned before, I've also used your cometgui.jar client and see the end event generated when using it as well. If I submit a chunk and the last chunk (0crlfcrlf) together, I see a read error on the server. If I submit a chunk and then submit the last chunk in two separate submissions, I see an end event on the server. Peter On Jan 24, 2008 12:44 PM, Filip Hanik - Dev Lists [EMAIL PROTECTED] wrote: even with your code, I wasn't able to replicate what you were seeing. what I would need to see what's going on for you: 1. a war file with your comet server, and source code 2. a test client 3. your server.xml Filip - 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]
Re: comet end event
$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=revrevision=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
Re: comet end event
); outputStream.flush(); } private void sendLastChunk() throws IOException { byte[] outputBytes = new String(0 + DELIMITER+DELIMITER).getBytes(ENCODING); outputStream.write(outputBytes); outputStream.flush(); } } 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): - 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]
Re: comet end event
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. 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. 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. 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). 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
Re: comet end event
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
Re: comet end event
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]
Re: comet end event
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]
comet end event
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]
Re: Comet Development
This post (http://www.nabble.com/comet-questions-td14673697.html#a14673697) contains test code for both a client comet servlet. See if it helps. On Jan 16, 2008 10:35 AM, Siobhan [EMAIL PROTECTED] wrote: To anyone who has successfully used Comet: I've been trying to use Comet with Tomcat 6.0 for a few weeks now and have been unsuccessful. I'm so frustrated with the lack of documentation and the unusable example that was given with Tomcat. Are there any step-by-step instructions on how to successfully implement a test program? -SB - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: comet questions
Anyone else experiencing comet timeout problems with the nio connector and the latest 6.0.x trunk? My cometEvent.setTimeout(...) setting is ignored, but I do receive comet timeouts based on the connectionTimeout setting for the nio connector. Setting the connectionTimeout to 10 secs gives me a comet timeout event every 10 secs. Setting it to 2 mins gives a comet timeout every 2 mins. The docs don't mention any link between the connectionTimeout settings and comet timeout events that I can find. Connector config: Connector port=80 protocol=org.apache.coyote.http11.Http11NioProtocol maxThreads=500 connectionTimeout=1 keepAliveTimeout=3 maxKeepAliveRequests=-1 socket.soKeepAlive=true socket.appReadBufSize=2048 socket.appWriteBufSize=2048 socket.rxBufSize=2048 socket.txBufSize=2048 acceptorThreadCount=2 redirectPort=8443 / On Jan 9, 2008 12:23 PM, Peter Warren [EMAIL PROTECTED] wrote: Using the nio connector from the latest 6.0.x trunk, I'm failing to receive any comet timeouts. I set the comet timeout to 5 secs but, after waiting much longer than 5 secs, the only two events I receive are begin and read. event: BEGIN, subtype: null for servlet: com.seekspeak.server.debug.CometTestServlet time: Wed Jan 09 12:12:28 PST 2008 on cometEvent: [EMAIL PROTECTED] with org.apache.tomcat.comet.timeout attribute: null with org.apache.tomcat.comet.timeout.support attribute: true event: READ, subtype: null for servlet: com.seekspeak.server.debug.CometTestServlet time: Wed Jan 09 12:12:28 PST 2008 on cometEvent: [EMAIL PROTECTED] with org.apache.tomcat.comet.timeout attribute: 5000 with org.apache.tomcat.comet.timeout.support attribute: true I see that the Http11NioProcessor changed some comet timeout specific code from the previous rev. Could this be having an impact? Below is my test client and test servlet. Am I doing something wrong? Thanks, Peter SERVLET --- public class CometTestServlet extends HttpServlet implements CometProcessor { public void event(CometEvent cometEvent) throws IOException, ServletException { System.out.println(event: + cometEvent.getEventType() + , subtype: + cometEvent.getEventSubType()); System.out.println(\tfor servlet: + this.getClass().getName()); System.out.println(\ttime: + new Date(System.currentTimeMillis())); System.out.println(\ton cometEvent: + cometEvent); System.out.println(\twith \org.apache.tomcat.comet.timeout\ attribute: + cometEvent.getHttpServletRequest().getAttribute(org.apache.tomcat.comet.timeout)); System.out.println(\twith \org.apache.tomcat.comet.timeout.support\ attribute: + cometEvent.getHttpServletRequest().getAttribute(org.apache.tomcat.comet.timeout.support)); if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) { cometEvent.setTimeout(5 * 1000); } else if (cometEvent.getEventType() == CometEvent.EventType.ERROR) { cometEvent.close(); } else if (cometEvent.getEventType() == CometEvent.EventType.END) { cometEvent.close(); } else if (cometEvent.getEventType() == CometEvent.EventType.READ) { handleReadEvent(cometEvent); } } private void handleReadEvent(CometEvent cometEvent) throws IOException, ServletException { ServerCometChannel talker = new ServerCometChannel(cometEvent); respond(talker); } private void respond(ServerCometChannel channel) throws IOException { String clientMessage = channel.receive(); if (clientMessage != null clientMessage.length() 0) { channel.send(comet succeeded); } } private class ServerCometChannel { private static final int OUTPUT_BUFFER_SIZE = 512; private CometEvent cometEvent; private InputStream inputStream; private PrintWriter outputWriter; public ServerCometChannel(CometEvent cometEvent) throws IOException, ServletException { this.cometEvent = cometEvent; inputStream = cometEvent.getHttpServletRequest().getInputStream(); OutputStream outputStream = cometEvent.getHttpServletResponse().getOutputStream(); this.outputWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream), OUTPUT_BUFFER_SIZE)); } private String receive() throws IOException { StringBuffer buffer = new StringBuffer(); byte[] buf = new byte[512]; while (inputStream.available() 0) { int n = inputStream.read(buf); if (n 0) { buffer.append(new String(buf, 0, n)); } } return buffer.toString(); } public void send(String
Re: comet client doesn't receive server response
What is interesting to me is that the exact same client code only using a different url (i.e. to a normal http servlet, not a comet servlet) succeeds. Is there something in comet response headers that an antivirus app or firewall would pick up on? Why would a request to a normal servlet succeed and a comet servlet fail? Keep in mind the comet servlet has been shown to be funtional on numerous other machines. I believe I disabled all firewalls and antivirus on the suspect machine, but I will double-check. Thanks for your response, Peter On Jan 15, 2008 9:37 AM, Leonardo Fraga [EMAIL PROTECTED] wrote: Hello, I've had problems with long http responses and some kind of antiviruses and internet firewalls (avg family, basically). They put a hook on the winsocket stack for http connections and buffer everything you are receiving, until the end (or some high amount of data), to run the checks. In my case, this buffering lasts for minutes, with no byte sent back to the browser. I think this can be a simple point to check... Hugs, Leonardo Fraga Web Developer [EMAIL PROTECTED] Peter Warren wrote: I posted this question along with some others recently. I'm re-posting it in its own thread with some additional information. I have a comet client app that works on all the machines I've tested except one. The failing machine sends a comet request to the server and then waits indefinitely for the response, even though the server has sent the response and flushed the buffer. I'm trying to figure out why the client doesn't receive the response and would really appreciate any tips. Server is latest from 6.0.x trunk and using nio connector. Failing machine info: - runs windows xp - windows firewall is turned off - fails on multiple networks, so it doesn't seem to be a router or firewall issue - computer has no problem with other network access - same test code pointed at a non-comet servlet (simply changing the url) succeeds!!! I used a socket monitoring tool to see if the client machine receives the response at all. It doesn't appear to. Below are traces from a successful machine and the failing machine. I'm not a sockets expert, so I don't really know what to look for, but the two things that stand out to me are: - failing machine uses localhost ip instead of its LAN ip (which is 192.168.1.102 according to ipconfig) - succeeding machine uses LAN ip - I don't understand why they're different - failing machine receives WSAEWOULDBLOCK error instead of server response I believe the WSAEWOULDBLOCK basically indicates that there's nothing on the socket to be read, which seems to indicate that the failing machine never receives the response at all. Is this a comet problem? Is it a routing problem? Anyone have any ideas for what the problem might be? Any tips on what I should investigate next? Thanks, Peter SUCCEEDING MACHINE SOCKET TRACE = Connect Address: 66.241.85.247:80 Return Value: 0 Error Code:0 GetSockName Address: 192.168.1.133:1104 Return Value: 0 Error Code:0 SetSockOpt - Level: SOL_SOCKET Opt Name: SO_KEEPALIVE Opt Len: 4 Return Value: 0 Error Code:0 01 00 00 00 Send --- Address: 192.168.1.133:1104 = 66.241.85.247:80 Flags: 0 Return Value: 0 Error Code:0 Data: POST /servlet/Receive HTTP/1.1 Host: www.seekspeak.com User-Agent: SeekSpeak Connection: keep-alive Content-Type: text/plain Transfer-Encoding: chunked 2c source_chat_id=192.168.1.1%3A486547763981705 Recv --- Address: 192.168.1.133:1104 = 66.241.85.247:80 Flags: 0 Return Value: 0 Error Code:0 Data: HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Set-Cookie: JSESSIONID=4618F4394D4924A5629628ED1CD2ADDE; Path=/ Transfer-Encoding: chunked Date: Thu, 10 Jan 2008 07:55:05 GMT 49 OK COMMAND INVITATION_ACCEPTED tutorial_client Invitation accepted... FAILING MACHINE SOCKET TRACE = Connect Address: 66.241.85.247:80 Return Value: 0 Error Code:0 GetSockName Address: 127.0.0.1:2085 Return Value: 0 Error Code:0 SetSockOpt - Level: SOL_SOCKET Opt Name: SO_KEEPALIVE Opt Len: 4 Return Value: 0 Error Code:0 01 00 00 00 Send --- Address: 127.0.0.1:2085 = 66.241.85.247:80 Flags: 0
comet client doesn't receive server response
I posted this question along with some others recently. I'm re-posting it in its own thread with some additional information. I have a comet client app that works on all the machines I've tested except one. The failing machine sends a comet request to the server and then waits indefinitely for the response, even though the server has sent the response and flushed the buffer. I'm trying to figure out why the client doesn't receive the response and would really appreciate any tips. Server is latest from 6.0.x trunk and using nio connector. Failing machine info: - runs windows xp - windows firewall is turned off - fails on multiple networks, so it doesn't seem to be a router or firewall issue - computer has no problem with other network access - same test code pointed at a non-comet servlet (simply changing the url) succeeds!!! I used a socket monitoring tool to see if the client machine receives the response at all. It doesn't appear to. Below are traces from a successful machine and the failing machine. I'm not a sockets expert, so I don't really know what to look for, but the two things that stand out to me are: - failing machine uses localhost ip instead of its LAN ip (which is 192.168.1.102 according to ipconfig) - succeeding machine uses LAN ip - I don't understand why they're different - failing machine receives WSAEWOULDBLOCK error instead of server response I believe the WSAEWOULDBLOCK basically indicates that there's nothing on the socket to be read, which seems to indicate that the failing machine never receives the response at all. Is this a comet problem? Is it a routing problem? Anyone have any ideas for what the problem might be? Any tips on what I should investigate next? Thanks, Peter SUCCEEDING MACHINE SOCKET TRACE = Connect Address: 66.241.85.247:80 Return Value: 0 Error Code:0 GetSockName Address: 192.168.1.133:1104 Return Value: 0 Error Code:0 SetSockOpt - Level: SOL_SOCKET Opt Name: SO_KEEPALIVE Opt Len: 4 Return Value: 0 Error Code:0 01 00 00 00 Send --- Address: 192.168.1.133:1104 = 66.241.85.247:80 Flags: 0 Return Value: 0 Error Code:0 Data: POST /servlet/Receive HTTP/1.1 Host: www.seekspeak.com User-Agent: SeekSpeak Connection: keep-alive Content-Type: text/plain Transfer-Encoding: chunked 2c source_chat_id=192.168.1.1%3A486547763981705 Recv --- Address: 192.168.1.133:1104 = 66.241.85.247:80 Flags: 0 Return Value: 0 Error Code:0 Data: HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Set-Cookie: JSESSIONID=4618F4394D4924A5629628ED1CD2ADDE; Path=/ Transfer-Encoding: chunked Date: Thu, 10 Jan 2008 07:55:05 GMT 49 OK COMMAND INVITATION_ACCEPTED tutorial_client Invitation accepted... FAILING MACHINE SOCKET TRACE = Connect Address: 66.241.85.247:80 Return Value: 0 Error Code:0 GetSockName Address: 127.0.0.1:2085 Return Value: 0 Error Code:0 SetSockOpt - Level: SOL_SOCKET Opt Name: SO_KEEPALIVE Opt Len: 4 Return Value: 0 Error Code:0 01 00 00 00 Send --- Address: 127.0.0.1:2085 = 66.241.85.247:80 Flags: 0 Return Value: 0 Error Code:0 Data: POST /servlet/Receive HTTP/1.1 Host: www.seekspeak.com User-Agent: SeekSpeak Connection: keep-alive Content-Type: text/plain Transfer-Encoding: chunked 2c source_chat_id=192.168.1.1%3A485374421886120 Select - Return Value: 0 Error Code:0 Recv --- Address: 127.0.0.1:2077 = 66.241.85.247:80 Flags: 0 Return Value: -1 Error Code:WSAEWOULDBLOCK - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
comet questions
I have some comet questions. I'm using the tomcat 6.0.x trunk as of last Friday. 1) My comet event timeout setting being honored. How come? I set the timeout for 3 hours but a timeout event gets generated every 2 minutes. If I inspect the comet event for which the timeout is triggered, I see a setting for the request attribute of: org.apache.tomcat.comet.timeout=1080. I set it as follows: public void event(CometEvent cometEvent) throws IOException, ServletException { ... if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) { // COMET_TIMEOUT = 3 * 60 * 60 * 1000 cometEvent.setTimeout(TimingConstants.COMET_TIMEOUT); Do I need to set something else as well? 2) Occasionally I'm getting a comet event of type ERROR without any subtype (i.e. not TIMEOUT, CLIENT_DISCONNECT, etc.). What does that indicate? I don't see any errors in my catalina log. 3) Reading the response from a comet servlet fails for one of my client machines. I wrote a simple test to check the problem. This test succeeds for many other users. For the failing client, the client request is received by the comet servlet, and the servlet's response is written and flushed to the stream. The client then simply waits indefinitely trying to read the response. The failing client is a Windows XP machine. Could anyone shed some light on why this might be happening, or give me some clues as to how to debug? Could it be a firewall issue on the client end, a router issue on my end? The test is currently up at: http://www.seekspeak.com/test.html. It tests: a http connection to a normal servlet, then a comet connection to a comet servlet using httpurlconnection, then a comet connection to a comet servlet using a socket. For the failing client, both comet tests fail. Below is some of the test code for the raw socket test. Thanks for any help! Peter CLIENT -- private void testCometConnection() throws IOException { ... URL url = new URL(http://www.seekspeak.com/CometTest;); channel = new CometChannel(url); Thread testThread = new Thread() { public void run() { try { channel.send(test); String received = channel.receive(); ... } } catch (IOException ioe) { ioe.printStackTrace(); } } }; testThread.start(); ... } private class CometChannel { private static final int INPUT_BUFFER_SIZE = 512; private static final int OUTPUT_BUFFER_SIZE = 512; private static final String DELIMITER = \r\n; private URL url; private BufferedReader inputReader; private PrintWriter outputWriter; private Socket socket; public CometChannel(URL url) throws IOException { this.url = url; initConnection(); } private void initSocket() throws IOException { int port = url.getPort(); port = (port 0) ? url.getDefaultPort() : port; try { socket = new Socket(url.getHost(), port); socket.setKeepAlive(true); inputReader = new BufferedReader(new InputStreamReader(socket.getInputStream()), INPUT_BUFFER_SIZE); outputWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()), OUTPUT_BUFFER_SIZE)); } catch (NoRouteToHostException nrthe) { System.out.println(host: + url.getHost()); nrthe.printStackTrace(); } } private void initConnection() throws IOException { initSocket(); sendHeaders(); } private void sendHeaders() { 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: CometTestApplet + DELIMITER); outputBuffer.append(Connection: keep-alive + DELIMITER); outputBuffer.append(Content-Type: text/plain + DELIMITER); outputBuffer.append(Transfer-Encoding: chunked + DELIMITER); outputBuffer.append(DELIMITER); synchronized (outputWriter) { outputWriter.print(outputBuffer.toString()); } } public void send(String chunkData) throws IOException { // chunk length field in hex String hexChunkLength = Integer.toHexString(chunkData.length()); StringBuffer outputBuffer = new StringBuffer(); outputBuffer.append(hexChunkLength); outputBuffer.append(DELIMITER); outputBuffer.append(chunkData);
Re: comet questions
Using the NIO connector: protocol=org.apache.coyote.http11.Http11NioProtocol. I'll add response.flushBuffer() and see if that helps. The tomcat version I was testing against was current with svn as of last Friday. I just updated and the only files that are new are: catalina.policy STATUS.txt changelog.xml Any ideas about the timeout setting or the comet error event without a subtype? Thanks for your response! Peter On Jan 7, 2008 12:44 PM, Filip Hanik - Dev Lists [EMAIL PROTECTED] wrote: what connector are you using? I would try to use response.flushBuffer when you wanna flush it out (ie after you've written to and flushed your stream). also, there have been some bug fixes, that you can get from SVN, or wait for 6.0.16 to come out Filip Peter Warren wrote: I have some comet questions. I'm using the tomcat 6.0.x trunk as of last Friday. 1) My comet event timeout setting being honored. How come? I set the timeout for 3 hours but a timeout event gets generated every 2 minutes. If I inspect the comet event for which the timeout is triggered, I see a setting for the request attribute of: org.apache.tomcat.comet.timeout=1080. I set it as follows: public void event(CometEvent cometEvent) throws IOException, ServletException { ... if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) { // COMET_TIMEOUT = 3 * 60 * 60 * 1000 cometEvent.setTimeout(TimingConstants.COMET_TIMEOUT); Do I need to set something else as well? 2) Occasionally I'm getting a comet event of type ERROR without any subtype (i.e. not TIMEOUT, CLIENT_DISCONNECT, etc.). What does that indicate? I don't see any errors in my catalina log. 3) Reading the response from a comet servlet fails for one of my client machines. I wrote a simple test to check the problem. This test succeeds for many other users. For the failing client, the client request is received by the comet servlet, and the servlet's response is written and flushed to the stream. The client then simply waits indefinitely trying to read the response. The failing client is a Windows XP machine. Could anyone shed some light on why this might be happening, or give me some clues as to how to debug? Could it be a firewall issue on the client end, a router issue on my end? The test is currently up at: http://www.seekspeak.com/test.html. It tests: a http connection to a normal servlet, then a comet connection to a comet servlet using httpurlconnection, then a comet connection to a comet servlet using a socket. For the failing client, both comet tests fail. Below is some of the test code for the raw socket test. Thanks for any help! Peter CLIENT -- private void testCometConnection() throws IOException { ... URL url = new URL(http://www.seekspeak.com/CometTest;); channel = new CometChannel(url); Thread testThread = new Thread() { public void run() { try { channel.send(test); String received = channel.receive(); ... } } catch (IOException ioe) { ioe.printStackTrace(); } } }; testThread.start(); ... } private class CometChannel { private static final int INPUT_BUFFER_SIZE = 512; private static final int OUTPUT_BUFFER_SIZE = 512; private static final String DELIMITER = \r\n; private URL url; private BufferedReader inputReader; private PrintWriter outputWriter; private Socket socket; public CometChannel(URL url) throws IOException { this.url = url; initConnection(); } private void initSocket() throws IOException { int port = url.getPort(); port = (port 0) ? url.getDefaultPort() : port; try { socket = new Socket(url.getHost(), port); socket.setKeepAlive(true); inputReader = new BufferedReader(new InputStreamReader(socket.getInputStream()), INPUT_BUFFER_SIZE); outputWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()), OUTPUT_BUFFER_SIZE)); } catch (NoRouteToHostException nrthe) { System.out.println(host: + url.getHost()); nrthe.printStackTrace(); } } private void initConnection() throws IOException { initSocket(); sendHeaders(); } private void sendHeaders() { String path = url.getPath(); StringBuffer outputBuffer = new StringBuffer
Re: Tomcat memory issues
As far as I under stand I should NOT close the stream object as I didn't open it. That's my understanding too. When I said I was keeping connections open, I meant I was opening connections from the client and not closing them. Since I'm using comet servlets, the server keeps the connections open until the client disconnects. When I open many connections, I see classes in my heap similar to those you show. If you keep a reference to the Request object tucked away somewhere on the server inadvertently, the associated buffers won't go away and memory will continue to grow. Is it possible that you're keeping a reference to the Request or any of the streams somewhere? Is it possible that some of your servlets aren't returning and thus never closing their connections? What classes are holding references to these classes? - org.apache.catalina.connector.ResponseFacade (ACCA) - class[] (ACCB) - org.apache.catalina.connector.Request (ACCC) Peter On 9/7/07, Morten [EMAIL PROTECTED] wrote: Peter Warren [EMAIL PROTECTED] skrev i en meddelelse news:[EMAIL PROTECTED] Is it possible you're caching Request or Response objects somewhere and not releasing them? I just did a bunch of memory profiling and many of the classes you mention are the same classes I see when I open and don't close a bunch of connections to the server. My code in the bottom of the servlet is such: ServletOutputStream stream = _response.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(stream); bos.write(bytes); stream.flush(); bos.close(); As far as I under stand I should NOT close the stream object as I didn't open it. Best regards, Morten - 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]
Re: Tomcat memory issues
Is it possible you're caching Request or Response objects somewhere and not releasing them? I just did a bunch of memory profiling and many of the classes you mention are the same classes I see when I open and don't close a bunch of connections to the server. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
comet webapp memory optimization
I have a webapp that maintains many concurrent comet connections. Transmissions between the client and server are small and infrequent. I'm trying to lessen the memory usage by playing with buffer configurations. To test various configurations, I wrote a client that opens 2000 connections to a comet servlet. Each connection sends a short message and receives a short message back from the server. I do not close the connections. I'm using the NetBeans 6.0 profiler to look at memory use. The first thing I did was configure the http connector with the following settings (maybe a little extreme, but I'm just playing here): socket.appReadBufSize=512 socket.appWriteBufSize=512 socket.rxBufSize=512 socket.txBufSize=512 These settings reduced vm heap memory use from 251 MB to 220 MB. Then I changed my comet servlet to use my own BufferedReader and PrintWriter with buffer sizes of 512k, instead of using the Reader from HttpServletRequest.getReader() and the Writer from HttpServletResponse.getWriter(), which both have larger default buffer sizes. This reduced memory use from 220 MB to 138 MB. At this point much of the memory was in char arrays in org.apache.catalina.connector.InputBuffer objects, and byte arrays in org.apache.catalina.connector.OutputBuffer objects. Since I couldn't find a way to tweak these buffer sizes with config settings or external code, I tried modifying the tomcat code. I changed the DEFAULT_BUFFER_SIZE in both those classes to 1024 from 8192. This reduced memory use from 138 MB to 95 MB. Now byte arrays in InternalNioInputBuffer and InternalNioOutputBuffer looked like promising targets. To modify these, I changed the maxHttpHeaderSize in Http11NioProtocol to 1024 from 8192. This reduced memory use from 95 MB to 66 MB. At this point my heap map shows the main consumers of memory as follows: Of the 66 MB on the heap: char[] account for 26% (below shows %s of the 26%) Parameters in Request 56% InputBuffer in Request 6% byte[] 19% (below shows %s of the 19%) BufferedInputFilter in Http11NioProcessor 19% OutputBuffer in Response 19% NioBufferHandler in NioEndpoint 19% InternalNioInputBuffer in Http11NioProcessor 20% InternalNioOutputBuffer in Http11NioProcessor 18% So... 1) Are any of the changes listed above bad ideas? What is the danger of sizing buffers too small? Is it just a performance hit, or is there a danger of losing data? 2) Is there a way for me to change the buffer sizes in InputBuffer, OutputBuffer, InternalNioInputBuffer, and InternalNioOutputBuffer without having to change Tomcat code? 3) Does anyone have other ideas for minimizing memory use in a many-connection, small-data-size webapp? 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]
comet read httpsession timeout
A comet read event doesn't update the last accessed time of an HttpSession -- which means comet read events will never prevent an http session (not the comet session) from timing out and the connection getting closed. Is that by design? If so, can anyone offer me suggestions on how to handle long-lived comet connections that may outlive the http session timeout? I had been hoping to periodically send a comet read event to update the access time of the http session. But, given that comet reads don't affect access time of the http session, it seems my best option is to periodically close the comet connection and open a new one. Or is there a way for me to programmatically update the http session access time (I couldn't find one in the HttpSession docs)? Any other thoughts? 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]
multiple comet requests
How do you send multiple requests to the same comet servlet? Sending multiple chunks of a single request is fine. My problem occurs after the client ends the chunked transaction by sending 0CRLFCRLF to the server. The comet servlet correctly registers the END event. But then the client subsequently tries to initiate a new chunked request by sending new http headers and a new chunk. The comet servlet receives a BEGIN event, immediately followed by an END event. A READ event is never generated for the new chunk. No ERROR events are registered either. Sequence: 1st request BEGIN READ END 2nd request BEGIN END - why an END event and not a READ? Below are my test client and test comet servlet. Any thoughts on what I'm doing wrong? (I apologize in advance if this is a lack of understanding of http on my part. I have looked at the specs and tried to follow the rules but am still running into problems.) Thanks, Peter - test servlet 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(100); if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) { log(Begin for session: + request.getSession(true).getId()); } 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().print(clientMessage); response.getWriter().flush(); } } private String read(HttpServletRequest request) throws IOException { InputStream is = request.getInputStream(); StringBuffer inputBuffer = new StringBuffer(); byte[] buf = new byte[512]; while (is.available() 0) { 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); } } return inputBuffer.toString(); } } /test servlet - test client import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class CometTestClient1 { public static final String ENCODING = ISO-8859-1; private Socket socket; private OutputStream out; public static void main(String[] args) throws Exception { CometTestClient1 test = new CometTestClient1(); test.test(); } public CometTestClient1() throws IOException { initConnection(); } private void initConnection() throws IOException { socket = new Socket(127.0.0.1, 80); socket.setKeepAlive(true); out = socket.getOutputStream(); sendHeaders(); } private void sendHeaders() throws IOException { println(GET /CometTest HTTP/1.1); println(Host: 127.0.0.1); println(User-Agent: test); println(Transfer-Encoding: chunked); println(Connection: keep-alive); } private void test() throws IOException { sendChunkedMessage(); try { Thread.sleep(6); } catch (InterruptedException ie) { ie.printStackTrace(); } // doesn't seem to matter if I create a new socket connection or not //initConnection(); sendHeaders(); sendChunkedMessage(); } private void sendChunkedMessage() throws IOException { println(); println(10); print(test data test 1); out.flush();
Re: multiple comet requests
Filip, thank you for your very prompt response! I replaced the tomcat-coyote.jar with yours and now get the following exception on startup. Is there another jar that I need to update? Thanks, Peter Aug 14, 2007 9:02:29 PM org.apache.tomcat.util.digester.Digester startElement SEVERE: Begin event threw error java.lang.NoSuchMethodError: org.apache.tomcat.util.IntrospectionUtils.setProperty(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V at org.apache.catalina.startup.SetAllPropertiesRule.begin(SetAllPropertiesRule.java:66) at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1358) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source) at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1644) at org.apache.catalina.startup.Catalina.load(Catalina.java:504) at org.apache.catalina.startup.Catalina.load(Catalina.java:538) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:260) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412) Filip Hanik - Dev Lists wrote: turns out that if the request is comet, the recycling of the input/output filter is not happening. I have fixed this, you can try the tomcat-coyote.jar from http://people.apache.org/~fhanik/tomcat/tomcat-coyote.jar Filip Filip Hanik - Dev Lists wrote: hi Peter, thanks for the example, I am able to reproduce this error, let me take a look and see why it is happening, Filip Peter Warren wrote: How do you send multiple requests to the same comet servlet? Sending multiple chunks of a single request is fine. My problem occurs after the client ends the chunked transaction by sending 0CRLFCRLF to the server. The comet servlet correctly registers the END event. But then the client subsequently tries to initiate a new chunked request by sending new http headers and a new chunk. The comet servlet receives a BEGIN event, immediately followed by an END event. A READ event is never generated for the new chunk. No ERROR events are registered either. Sequence: 1st request BEGIN READ END 2nd request BEGIN END - why an END event and not a READ? Below are my test client and test comet servlet. Any thoughts on what I'm doing wrong? (I apologize in advance if this is a lack of understanding of http on my part. I have looked at the specs and tried to follow the rules but am still running into problems.) Thanks, Peter - test servlet 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(100); if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) { log(Begin for session: + request.getSession(true).getId()); } 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
Re: comet read event
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(100); 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=2 keepAliveTimeout=12 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
Re: [solved] comet read event
My client code was the problem. I had been thinking of the comet interaction with the server as similar to a socket, open it once and then read and write merrily from either end. I forgot that comet is still operating over http and the client needs to send http headers for each request. So the fix in my client code is simply to open a new HttpURLConnection for each client request, which hopefully does not establish a new socket connection to the server each time (Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances -- from javadoc for HttpURLConnection). See added initConnection() line below. Peter ### from CometTestClient below ### public void test() throws IOException { out.println(test 1); out.flush(); String line = read(urlConn.getInputStream()); System.out.println(line); ---initConnection(); // reconnect to url - sends new http headers out.println(test 2); out.flush(); line = read(urlConn.getInputStream()); System.out.println(line); out.close(); urlConn.disconnect(); } 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
Re: [maybe not solved] comet read event
Hmm, ok. Sending the headers up causes the comet servlet to behave as I expected, one BEGIN event generated on the first client request and one READ event generated on the second request. In my simple test, the comet servlet doesn't receive the headers as data. If I don't send up the headers on the second request, the READ event is never generated (in fact no event is generated) and the client hangs waiting for a response from the comet servlet. Doesn't your cometgui send the headers with each request? Peter Filip Hanik - Dev Lists wrote: you're treading dangerous waters my friend. the comet is somewhat like a real socket, and sending up new HTTP headers might end up just being data for the Comet servlet. Filip Peter Warren wrote: My client code was the problem. I had been thinking of the comet interaction with the server as similar to a socket, open it once and then read and write merrily from either end. I forgot that comet is still operating over http and the client needs to send http headers for each request. So the fix in my client code is simply to open a new HttpURLConnection for each client request, which hopefully does not establish a new socket connection to the server each time (Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances -- from javadoc for HttpURLConnection). See added initConnection() line below. Peter ### from CometTestClient below ### public void test() throws IOException { out.println(test 1); out.flush(); String line = read(urlConn.getInputStream()); System.out.println(line); ---initConnection(); // reconnect to url - sends new http headers out.println(test 2); out.flush(); line = read(urlConn.getInputStream()); System.out.println(line); out.close(); urlConn.disconnect(); } 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
Re: comet read event
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
Re: comet read event
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=2 keepAliveTimeout=12 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
comet read event
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(100); 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
comet read event
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(100); if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) { log(Begin for session: + request.getSession(true).getId()); BufferedReader reader = cometEvent.getHttpServletRequest().getReader(); String line = reader.readLine
Re: virtual host getRealPath
Chris, The application is an image gallery. I want to be able to drop images into directories anywhere underneath the gallery webapp directory and have the images automatically displayed as thumbnails in a table. Users can click on a thumbnail for the full-size image. I have an index.jsp file that creates thumbnails for all the images in a directory and then generates the html to display them. Since I don't want to have to drop an index.jsp file into every image directory, I set up a forwarding filter that forwards any request for a directory to /index.jsp (the filter ignores other request urls). To get the real path of the directory that corresponds to the requested url, I use: String servletPath = (String) request.getAttribute(javax.servlet.forward.servlet_path); String realPath = application.getRealPath(servletPath); You still have to add the request's URI to the end of that. I don't seem to. For example, a request for: http://www.nomad.org/gallery/test yields a servlet path of /test/ and a real path of: C:\Documents and Settings\Peter\My Documents\dev\webapps\www.nomad.org\gallery\pg which is just what I need. Now with the real path, I can process the target image directory by making thumbnails if necessary and laying out the html thumbnail table. It's up and working at http://www.nomad.org/gallery. Peter - Cheap Talk? Check out Yahoo! Messenger's low PC-to-Phone call rates.
Re: virtual host getRealPath
Hi Chris, Thanks for your response. After poking around a little more, it seems that the call application.getRealPath(request.getServletPath()) provides the proper local file path for me. Any reason not to use that? Peter Christopher Schultz [EMAIL PROTECTED] wrote: Peter, I'm trying to figure out why I get repeated directory names when calling application.getRealPath(request.getRequestURI()) from an index.jsp file. Clearly there's something about virtual hosts and contexts that I'm missing. I suppose you /could/ do this, but usually URIs and directory structures usually don't map exactly to one another. A request for the url: http://www.nomad.org/gallery/ C:\Documents and Settings\Peter\My Documents\dev\webapps\www.nomad.org\gallery\gallery Yeah. Since your URL contains the prefix /gallery already, it's being added. When you call getRealPath, you're getting something rooted in ...\dev\webapps\www.nomad.org\gallery, which is the root of your webapp. Since /gallery in the URI, too, you're doubling it. You need to clip out the context path. This ought to do it for you: String path = request.getRequestURI(); if(path.startsWith(request.getContextPath())) path = path.substring(request.getContextPath()); path = application.getRealPath(path); Note that letting users' URIs drive files being loaded from the disk might be considered a security risk. I don't know your deployment model or anything like that; I just figured I'd mention it. Hope that helps, -chris - Cheap Talk? Check out Yahoo! Messenger's low PC-to-Phone call rates.
virtual host getRealPath
I'm trying to figure out why I get repeated directory names when calling application.getRealPath(request.getRequestURI()) from an index.jsp file. Clearly there's something about virtual hosts and contexts that I'm missing. Using Tomcat 5.5 6.0 in standalone mode under Windows XP, I see the following behavior: A request for the url: http://www.nomad.org/gallery/ yields a real path of: C:\Documents and Settings\Peter\My Documents\dev\webapps\www.nomad.org\gallery\gallery (note the duplication of the gallery directory) Why? In my server.xml file I defined this virtual host: Host name=www.nomad.org appBase=C:\Documents and Settings\Peter\My Documents\dev\webapps\www.nomad.org unpackWARs=true autoDeploy=true xmlValidationfiltered=false xmlNamespaceAware=false /Host If I don't define any contexts, the problem occurs. The problem also occurs if I have either of the following contexts defined for this host: Context path=/gallery docBase=gallery / or Context path=/gallery docBase=/gallery / If I set the gallery context to: Context path=/gallery docBase= / the duplicate folder name goes away, but my gallery web.xml does not get read. Thanks for any help, Peter - Cheap Talk? Check out Yahoo! Messenger's low PC-to-Phone call rates.
threads, performance, and exceptions
I have an application that links users so they can chat. My client operates within a browser. To be firewall friendly and avoid client server sockets listening for incoming requests, I implemented the client so that it makes http requests and sits and waits (maybe for minutes on end) until it gets a response. And each client has 2 threads that are constantly waiting for an http response from 2 different urls (which ties up 2 servlet threads). I knew full well that this would be thread heavy on the tomcat server side but thought I'd try it out. The server is tomcat 5.5.20 running on Windows XP Pro with 1GB of RAM. After some preliminary load testing, I find I'm able to handle about 500 simulated users (each sending a message every 30 seconds) concurrently communicating before getting connection refused messages. I would like to improve that. So with each client having 2 threads constantly waiting on servlet requests, that's 2 servlet threads per client or 1000 threads on the server, which seems like a lot to me. With 500 clients communicating every 30 seconds, fairly evenly distributed, that's about 16 requests per second. It seems like I should be able to do better than that. Initially when running my load test, I ran into OutOfMemoryErrors: unable to create new native thread. Lowering the thread stack size in Tomcat's configuration dialog seemed to help. Now the limiting issue is that my clients receive connection timed out and read timed out messages. On the client I see the following stacks: java.net.ConnectException: Connection timed out: connect at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.PlainSocketImpl.doConnect(Unknown Source) at java.net.PlainSocketImpl.connectToAddress(Unknown Source) at java.net.PlainSocketImpl.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at sun.net.NetworkClient.doConnect(Unknown Source) at sun.net.www.http.HttpClient.openServer(Unknown Source) at sun.net.www.http.HttpClient.openServer(Unknown Source) at sun.net.www.http.HttpClient.init(Unknown Source) at sun.net.www.http.HttpClient.New(Unknown Source) at sun.net.www.http.HttpClient.New(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source) at com.seekspeak.applet.URLTalker.initConnection(URLTalker.java:44) at com.seekspeak.applet.URLTalker.send(URLTalker.java:50) at com.seekspeak.test.load.RecipientTest$RefreshThread.run(RecipientTest.java:206) java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(Unknown Source) at java.io.BufferedInputStream.fill(Unknown Source) at java.io.BufferedInputStream.read1(Unknown Source) at java.io.BufferedInputStream.read(Unknown Source) at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source) at sun.net.www.http.HttpClient.parseHTTP(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown So urce) at java.net.HttpURLConnection.getResponseCode(Unknown Source) at com.seekspeak.applet.URLTalker.send(URLTalker.java:54) at com.seekspeak.test.load.Communicator$ListenThread.run(Communicator.ja va:217) In the catalina log, the only problem I see is this stack: Oct 1, 2006 7:59:01 PM org.apache.catalina.core.StandardWrapperValve invoke WARNING: Servlet.service() for servlet invoker threw exception java.net.SocketException: Connection reset at java.net.SocketInputStream.read(Unknown Source) at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:747) at org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:777) at org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:115) at org.apache.coyote.http11.InternalInputBuffer.doRead(InternalInputBuffer.java:712) at org.apache.coyote.Request.doRead(Request.java:418) ... CPU-wise the server never breaks a sweat, rarely rising above 5% cpu. My load test client is running on a separate machine from the server. My question is: how can I best improve the performance? Is the server really refusing client connections or is the load test bogging down and reporting spurious messages (the load test uses many threads as well)? Is the high # of threads on the server a problem? Would running on Linux or another OS help? Is there a way for me to minimize the # of servlet threads required? Since my servlet threads don't really do anything but sit around blocking until being notified to complete the client's request, it seems like I could just have a small number of threads and keep