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="10000" keepAliveTimeout="30000"
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 msg) {
> synchronized (cometEvent.getHttpServletResponse()) {
> outputWriter.print(msg);
> outputWriter.flush();
> try {
> cometEvent.getHttpServletResponse().flushBuffer();
> } catch (IOException ioe) {
> ioe.printStackTrace();
> }
> }
> }
> }
> }
>
> CLIENT
> ----------
> public class CometTest {
>
> public static void main(String[] args) throws Exception {
> CometTest test = new CometTest();
> test.test();
> }
>
> private void test() throws Exception {
> URL url = new URL("http://www.seekspeak.com/CometTest");
> CometChannel channel = new CometChannel(url);
> channel.send("test");
> String received = channel.receive();
> System.out.println("received: " + received);
> Thread.sleep(60 * 60 * 1000);
> }
>
> 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;
>
> private boolean firstRead = true;
>
>
> 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 {
> String hexChunkLength = Integer.toHexString(chunkData.length());
>
> StringBuffer outputBuffer = new StringBuffer();
> outputBuffer.append(hexChunkLength);
> outputBuffer.append(DELIMITER);
> outputBuffer.append(chunkData);
> outputBuffer.append(DELIMITER);
> synchronized (outputWriter) {
> outputWriter.print(outputBuffer.toString());
> outputWriter.flush();
> }
> }
>
> private String readChunk() throws IOException {
> StringBuffer inputBuffer = new StringBuffer();
> String hexChunkSize = inputReader.readLine();
> System.out.println("chunk size: " + hexChunkSize);
> if (hexChunkSize != null) {
> int chunkSize = Integer.parseInt(hexChunkSize, 16);
> int charsRead = 0;
>
> char[] buf = new char[chunkSize];
> do {
> int n = inputReader.read(buf);
> charsRead += n;
> if (n > 0) {
> inputBuffer.append(new String(buf, 0, n));
> } else if (n < 0) {
> // occurs when connection is closed, often in response
> // to http session timeout from server
> throw new IOException("no bytes read");
> }
> } while (charsRead < chunkSize);
> // extra \r\n sent after chunk - part of protocol
> inputReader.readLine();
> }
> return inputBuffer.toString();
> }
>
> public String receive() throws IOException {
> if (firstRead) {
> firstRead = false;
> readHeaders();
> }
> return readChunk();
> }
>
> private void readHeaders() throws IOException {
> String header;
> while ((header = inputReader.readLine()) != null) {
> System.out.println("header: " + header);
> if (header.length() == 0) {
> break;
> }
> }
> }
> }
> }
>
>
>
> On Jan 7, 2008 4:43 PM, Filip Hanik - Dev Lists <[EMAIL PROTECTED]> wrote:
> > The time when it is called without a subtype, is if the
> > application(servlet) has an unhandled exception
> >
> > in terms of timeout, that should work just dandy, unless the client
> > disconnects, at which point at which point you might get a subtype of
> > IOEXCEPTION, or CLIENT_DISCONNECT
> > depending on the OS
> >
> > Filip
> >
> >
> > Peter Warren wrote:
> > > 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=10800000.
> > >>>
> > >>> 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);
> > >>> outputBuffer.append(DELIMITER);
> > >>> synchronized (outputWriter) {
> > >>> outputWriter.print(outputBuffer.toString());
> > >>> outputWriter.flush();
> > >>> }
> > >>> }
> > >>>
> > >>> private String readChunk() throws IOException {
> > >>> StringBuffer inputBuffer = new StringBuffer();
> > >>> String hexChunkSize = inputReader.readLine();
> > >>> if (hexChunkSize != null) {
> > >>> int chunkSize = Integer.parseInt(hexChunkSize, 16);
> > >>> int charsRead = 0;
> > >>>
> > >>> char[] buf = new char[chunkSize];
> > >>> do {
> > >>> int n = inputReader.read(buf);
> > >>> charsRead += n;
> > >>> if (n > 0) {
> > >>> inputBuffer.append(new String(buf, 0, n));
> > >>> } else if (n < 0) {
> > >>> // occurs when connection is closed, often in
> > >>> response
> > >>> // to http session timeout from server
> > >>> throw new IOException("no bytes read");
> > >>> }
> > >>> } while (charsRead < chunkSize);
> > >>> // extra \r\n sent after chunk - part of protocol
> > >>> inputReader.readLine();
> > >>> }
> > >>> return inputBuffer.toString();
> > >>> }
> > >>>
> > >>> public String receive() throws IOException {
> > >>> readHeaders();
> > >>> return readChunk();
> > >>> }
> > >>>
> > >>> private void readHeaders() throws IOException {
> > >>> String header;
> > >>> while ((header = inputReader.readLine()) != null) {
> > >>> System.out.println("header: " + header);
> > >>> if (header.length() == 0) {
> > >>> break;
> > >>> }
> > >>> }
> > >>> }
> > >>> ...
> > >>> }
> > >>>
> > >>> SERVER
> > >>> ------
> > >>> 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();
> > >>> HttpSession httpSession = request.getSession(true);
> > >>> if (cometEvent.getEventType() == CometEvent.EventType.BEGIN) {
> > >>> cometEvent.setTimeout(3 * 60 * 60 * 1000); // 3 hours
> > >>> // tell the http session not to timeout - will invalidate
> > >>> it on
> > >>> // error or end
> > >>> httpSession.setMaxInactiveInterval(-1);
> > >>> } else if (cometEvent.getEventType() ==
> > >>> CometEvent.EventType.ERROR) {
> > >>> handleErrorEvent(cometEvent, httpSession);
> > >>> } else if (cometEvent.getEventType() ==
> > >>> CometEvent.EventType.END) {
> > >>> close(cometEvent, httpSession);
> > >>> } else if (cometEvent.getEventType() ==
> > >>> CometEvent.EventType.READ) {
> > >>> handleReadEvent(cometEvent);
> > >>> }
> > >>> }
> > >>>
> > >>> protected void handleErrorEvent(CometEvent cometEvent, HttpSession
> > >>> httpSession) throws IOException {
> > >>> if (cometEvent.getEventSubType() !=
> > >>> CometEvent.EventSubType.TIMEOUT) {
> > >>> close(cometEvent, httpSession);
> > >>> }
> > >>> }
> > >>>
> > >>> private void close(CometEvent cometEvent, HttpSession httpSession)
> > >>> throws IOException {
> > >>> cometEvent.close();
> > >>> httpSession.invalidate();
> > >>> }
> > >>>
> > >>> 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 msg) {
> > >>> synchronized (cometEvent.getHttpServletResponse()) {
> > >>> outputWriter.print(msg);
> > >>> outputWriter.flush();
> > >>> }
> > >>> }
> > >>>
> > >>> public void close() throws IOException {
> > >>> inputStream.close();
> > >>> outputWriter.close();
> > >>> }
> > >>> }
> > >>>
> > >>> ---------------------------------------------------------------------
> > >>> To start a new topic, e-mail: [email protected]
> > >>> To unsubscribe, e-mail: [EMAIL PROTECTED]
> > >>> For additional commands, e-mail: [EMAIL PROTECTED]
> > >>>
> > >>>
> > >>>
> > >>>
> > >>>
> > >> ---------------------------------------------------------------------
> > >> To start a new topic, e-mail: [email protected]
> > >> To unsubscribe, e-mail: [EMAIL PROTECTED]
> > >> For additional commands, e-mail: [EMAIL PROTECTED]
> > >>
> > >>
> > >>
> > >
> > > ---------------------------------------------------------------------
> > > To start a new topic, e-mail: [email protected]
> > > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > > For additional commands, e-mail: [EMAIL PROTECTED]
> > >
> > >
> > >
> > >
> >
> >
> > ---------------------------------------------------------------------
> > To start a new topic, e-mail: [email protected]
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
>
---------------------------------------------------------------------
To start a new topic, e-mail: [email protected]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]