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]