blob: 731d76a262e8daced39dac502657a875ee154894 [file] [log] [blame]
Hongqing Liufd5ee812014-05-10 16:32:51 +08001<html><head><META http-equiv="Content-Type" content="text/html; charset=iso-8859-1"><title>Apache Tomcat 6.0 (6.0.39) - Advanced IO and Tomcat</title><meta name="author" content="Remy Maucherat"><style type="text/css" media="print">
2 .noPrint {display: none;}
3 td#mainBody {width: 100%;}
4 </style></head><body bgcolor="#ffffff" text="#000000" link="#525D76" alink="#525D76" vlink="#525D76"><table border="0" width="100%" cellspacing="0"><!--PAGE HEADER--><tr><td><!--PROJECT LOGO--><a href="http://tomcat.apache.org/"><img src="./images/tomcat.gif" align="right" alt="
5 The Apache Tomcat Servlet/JSP Container
6 " border="0"></a></td><td><h1><font face="arial,helvetica,sanserif">Apache Tomcat 6.0</font></h1><font face="arial,helvetica,sanserif">Version 6.0.39, Jan 27 2014</font></td><td><!--APACHE LOGO--><a href="http://www.apache.org/"><img src="./images/asf-logo.gif" align="right" alt="Apache Logo" border="0"></a></td></tr></table><table border="0" width="100%" cellspacing="4"><!--HEADER SEPARATOR--><tr><td colspan="2"><hr noshade="noshade" size="1"></td></tr><tr><!--LEFT SIDE NAVIGATION--><td width="20%" valign="top" nowrap="nowrap" class="noPrint"><p><strong>Links</strong></p><ul><li><a href="index.html">Docs Home</a></li><li><a href="http://wiki.apache.org/tomcat/FAQ">FAQ</a></li></ul><p><strong>User Guide</strong></p><ul><li><a href="introduction.html">1) Introduction</a></li><li><a href="setup.html">2) Setup</a></li><li><a href="appdev/index.html">3) First webapp</a></li><li><a href="deployer-howto.html">4) Deployer</a></li><li><a href="manager-howto.html">5) Manager</a></li><li><a href="realm-howto.html">6) Realms and AAA</a></li><li><a href="security-manager-howto.html">7) Security Manager</a></li><li><a href="jndi-resources-howto.html">8) JNDI Resources</a></li><li><a href="jndi-datasource-examples-howto.html">9) JDBC DataSources</a></li><li><a href="class-loader-howto.html">10) Classloading</a></li><li><a href="jasper-howto.html">11) JSPs</a></li><li><a href="ssl-howto.html">12) SSL</a></li><li><a href="ssi-howto.html">13) SSI</a></li><li><a href="cgi-howto.html">14) CGI</a></li><li><a href="proxy-howto.html">15) Proxy Support</a></li><li><a href="mbeans-descriptor-howto.html">16) MBean Descriptor</a></li><li><a href="default-servlet.html">17) Default Servlet</a></li><li><a href="cluster-howto.html">18) Clustering</a></li><li><a href="balancer-howto.html">19) Load Balancer</a></li><li><a href="connectors.html">20) Connectors</a></li><li><a href="monitoring.html">21) Monitoring and Management</a></li><li><a href="logging.html">22) Logging</a></li><li><a href="apr.html">23) APR/Native</a></li><li><a href="virtual-hosting-howto.html">24) Virtual Hosting</a></li><li><a href="aio.html">25) Advanced IO</a></li><li><a href="extras.html">26) Additional Components</a></li><li><a href="maven-jars.html">27) Mavenized</a></li></ul><p><strong>Reference</strong></p><ul><li><a href="RELEASE-NOTES.txt">Release Notes</a></li><li><a href="config/index.html">Configuration</a></li><li><a href="api/index.html">Javadocs</a></li><li><a href="http://tomcat.apache.org/connectors-doc/">JK 1.2 Documentation</a></li></ul><p><strong>Apache Tomcat Development</strong></p><ul><li><a href="building.html">Building</a></li><li><a href="changelog.html">Changelog</a></li><li><a href="http://wiki.apache.org/tomcat/TomcatVersions">Status</a></li><li><a href="developers.html">Developers</a></li><li><a href="architecture/index.html">Architecture</a></li><li><a href="funcspecs/index.html">Functional Specs.</a></li></ul></td><!--RIGHT SIDE MAIN BODY--><td width="80%" valign="top" align="left" id="mainBody"><h1>Apache Tomcat 6.0</h1><h2>Advanced IO and Tomcat</h2><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Table of Contents"><!--()--></a><a name="Table_of_Contents"><strong>Table of Contents</strong></a></font></td></tr><tr><td><blockquote>
7<ul><li><a href="#Introduction">Introduction</a></li><li><a href="#Comet_support">Comet support</a><ol><li><a href="#CometEvent">CometEvent</a></li><li><a href="#CometFilter">CometFilter</a></li><li><a href="#Example_code">Example code</a></li><li><a href="#Comet_timeouts">Comet timeouts</a></li></ol></li><li><a href="#Asynchronous_writes">Asynchronous writes</a></li></ul>
8</blockquote></td></tr></table><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Introduction"><strong>Introduction</strong></a></font></td></tr><tr><td><blockquote>
9
10 <p>
11 With usage of APR or NIO APIs as the basis of its connectors, Tomcat is
12 able to provide a number of extensions over the regular blocking IO
13 as provided with support for the Servlet API.
14 </p>
15
16 <p>
17 <b>IMPORTANT NOTE: Usage of these features requires using the APR or NIO
18 HTTP connectors. The classic java.io HTTP connector and the AJP connectors
19 do not support them.</b>
20 </p>
21
22 </blockquote></td></tr></table><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Comet support"><!--()--></a><a name="Comet_support"><strong>Comet support</strong></a></font></td></tr><tr><td><blockquote>
23
24 <p>
25 Comet support allows a servlet to process IO asynchronously, receiving
26 events when data is available for reading on the connection (rather than
27 always using a blocking read), and writing data back on connections
28 asynchronously (most likely responding to some event raised from some
29 other source).
30 </p>
31
32 <table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#828DA6"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="CometEvent"><strong>CometEvent</strong></a></font></td></tr><tr><td><blockquote>
33
34 <p>
35 Servlets which implement the <code>org.apache.catalina.CometProcessor</code>
36 interface will have their event method invoked rather than the usual service
37 method, according to the event which occurred. The event object gives
38 access to the usual request and response objects, which may be used in the
39 usual way. The main difference is that those objects remain valid and fully
40 functional at any time between processing of the BEGIN event until processing
41 an END or ERROR event.
42 The following event types exist:
43 </p>
44
45 <ul>
46 <li>EventType.BEGIN: will be called at the beginning
47 of the processing of the connection. It can be used to initialize any relevant
48 fields using the request and response objects. Between the end of the processing
49 of this event, and the beginning of the processing of the end or error events,
50 it is possible to use the response object to write data on the open connection.
51 Note that the response object and dependent OutputStream and Writer are still
52 not synchronized, so when they are accessed by multiple threads,
53 synchronization is mandatory. After processing the initial event, the request
54 is considered to be committed.</li>
55 <li>EventType.READ: This indicates that input data is available, and that one read can be made
56 without blocking. The available and ready methods of the InputStream or
57 Reader may be used to determine if there is a risk of blocking: the servlet
58 should read while data is reported available. When encountering a read error,
59 the servlet should report it by propagating the exception properly. Throwing
60 an exception will cause the error event to be invoked, and the connection
61 will be closed.
62 Alternately, it is also possible to catch any exception, perform clean up
63 on any data structure the servlet may be using, and using the close method
64 of the event. It is not allowed to attempt reading data from the request
65 object outside of the execution of this method.<br>
66 On some platforms, like Windows, a client disconnect is indicated by a READ event.
67 Reading from the stream may result in -1, an IOException or an EOFException.
68 Make sure you properly handle all these three cases.
69 If you don't catch the IOException, Tomcat will instantly invoke your event chain with an ERROR as
70 it catches the error for you, and you will be notified of the error at that time.
71 </li>
72 <li>EventType.END: End may be called to end the processing of the request. Fields that have
73 been initialized in the begin method should be reset. After this event has
74 been processed, the request and response objects, as well as all their dependent
75 objects will be recycled and used to process other requests. End will also be
76 called when data is available and the end of file is reached on the request input
77 (this usually indicates the client has pipelined a request).</li>
78 <li>EventType.ERROR: Error will be called by the container in the case where an IO exception
79 or a similar unrecoverable error occurs on the connection. Fields that have
80 been initialized in the begin method should be reset. After this event has
81 been processed, the request and response objects, as well as all their dependent
82 objects will be recycled and used to process other requests.</li>
83 </ul>
84
85 <p>
86 There are some event subtypes which allow finer processing of events (note: some of these
87 events require usage of the org.apache.catalina.valves.CometConnectionManagerValve valve):
88 </p>
89
90 <ul>
91 <li>EventSubType.TIMEOUT: The connection timed out (sub type of ERROR); note that this ERROR
92 type is not fatal, and the connection will not be closed unless the servlet uses the close
93 method of the event.
94 </li>
95 <li>EventSubType.CLIENT_DISCONNECT: The client connection was closed (sub type of ERROR).
96 </li>
97 <li>EventSubType.IOEXCEPTION: An IO exception occurred, such as invalid content, for example,
98 an invalid chunk block (sub type of ERROR).
99 </li>
100 <li>EventSubType.WEBAPP_RELOAD: The web application is being reloaded (sub type of END).
101 </li>
102 <li>EventSubType.SESSION_END: The servlet ended the session (sub type of END).
103 </li>
104 </ul>
105
106 <p>
107 As described above, the typical lifecycle of a Comet request will consist in a series of
108 events such as: BEGIN -&gt; READ -&gt; READ -&gt; READ -&gt; ERROR/TIMEOUT. At any time, the servlet
109 may end processing of the request by using the close method of the event object.
110 </p>
111
112 </blockquote></td></tr></table>
113
114 <table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#828DA6"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="CometFilter"><strong>CometFilter</strong></a></font></td></tr><tr><td><blockquote>
115
116 <p>
117 Similar to regular filters, a filter chain is invoked when comet events are processed.
118 These filters should implement the CometFilter interface (which works in the same way as
119 the regular Filter interface), and should be declared and mapped in the deployment
120 descriptor in the same way as a regular filter. The filter chain when processing an event
121 will only include filters which match all the usual mapping rules, and also implement
122 the CometFiler interface.
123 </p>
124
125 </blockquote></td></tr></table>
126
127 <table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#828DA6"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Example code"><!--()--></a><a name="Example_code"><strong>Example code</strong></a></font></td></tr><tr><td><blockquote>
128
129 <p>
130 The following pseudo code servlet implements asynchronous chat functionality using the API
131 described above:
132 </p>
133
134 <div align="left"><table cellspacing="4" cellpadding="0" border="0"><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#ffffff" height="1"><pre>
135public class ChatServlet
136 extends HttpServlet implements CometProcessor {
137
138 protected ArrayList&lt;HttpServletResponse&gt; connections =
139 new ArrayList&lt;HttpServletResponse&gt;();
140 protected MessageSender messageSender = null;
141
142 public void init() throws ServletException {
143 messageSender = new MessageSender();
144 Thread messageSenderThread =
145 new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]");
146 messageSenderThread.setDaemon(true);
147 messageSenderThread.start();
148 }
149
150 public void destroy() {
151 connections.clear();
152 messageSender.stop();
153 messageSender = null;
154 }
155
156 /**
157 * Process the given Comet event.
158 *
159 * @param event The Comet event that will be processed
160 * @throws IOException
161 * @throws ServletException
162 */
163 public void event(CometEvent event)
164 throws IOException, ServletException {
165 HttpServletRequest request = event.getHttpServletRequest();
166 HttpServletResponse response = event.getHttpServletResponse();
167 if (event.getEventType() == CometEvent.EventType.BEGIN) {
168 log("Begin for session: " + request.getSession(true).getId());
169 PrintWriter writer = response.getWriter();
170 writer.println("&lt;!doctype html public \"-//w3c//dtd html 4.0 transitional//en\"&gt;");
171 writer.println("&lt;head&gt;&lt;title&gt;JSP Chat&lt;/title&gt;&lt;/head&gt;&lt;body bgcolor=\"#FFFFFF\"&gt;");
172 writer.flush();
173 synchronized(connections) {
174 connections.add(response);
175 }
176 } else if (event.getEventType() == CometEvent.EventType.ERROR) {
177 log("Error for session: " + request.getSession(true).getId());
178 synchronized(connections) {
179 connections.remove(response);
180 }
181 event.close();
182 } else if (event.getEventType() == CometEvent.EventType.END) {
183 log("End for session: " + request.getSession(true).getId());
184 synchronized(connections) {
185 connections.remove(response);
186 }
187 PrintWriter writer = response.getWriter();
188 writer.println("&lt;/body&gt;&lt;/html&gt;");
189 event.close();
190 } else if (event.getEventType() == CometEvent.EventType.READ) {
191 InputStream is = request.getInputStream();
192 byte[] buf = new byte[512];
193 do {
194 int n = is.read(buf); //can throw an IOException
195 if (n &gt; 0) {
196 log("Read " + n + " bytes: " + new String(buf, 0, n)
197 + " for session: " + request.getSession(true).getId());
198 } else if (n &lt; 0) {
199 error(event, request, response);
200 return;
201 }
202 } while (is.available() &gt; 0);
203 }
204 }
205
206 public class MessageSender implements Runnable {
207
208 protected boolean running = true;
209 protected ArrayList&lt;String&gt; messages = new ArrayList&lt;String&gt;();
210
211 public MessageSender() {
212 }
213
214 public void stop() {
215 running = false;
216 }
217
218 /**
219 * Add message for sending.
220 */
221 public void send(String user, String message) {
222 synchronized (messages) {
223 messages.add("[" + user + "]: " + message);
224 messages.notify();
225 }
226 }
227
228 public void run() {
229
230 while (running) {
231
232 if (messages.size() == 0) {
233 try {
234 synchronized (messages) {
235 messages.wait();
236 }
237 } catch (InterruptedException e) {
238 // Ignore
239 }
240 }
241
242 synchronized (connections) {
243 String[] pendingMessages = null;
244 synchronized (messages) {
245 pendingMessages = messages.toArray(new String[0]);
246 messages.clear();
247 }
248 // Send any pending message on all the open connections
249 for (int i = 0; i &lt; connections.size(); i++) {
250 try {
251 PrintWriter writer = connections.get(i).getWriter();
252 for (int j = 0; j &lt; pendingMessages.length; j++) {
253 writer.println(pendingMessages[j] + "&lt;br&gt;");
254 }
255 writer.flush();
256 } catch (IOException e) {
257 log("IOExeption sending message", e);
258 }
259 }
260 }
261
262 }
263
264 }
265
266 }
267
268}
269 </pre></td><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr></table></div>
270
271 </blockquote></td></tr></table>
272 <table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#828DA6"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Comet timeouts"><!--()--></a><a name="Comet_timeouts"><strong>Comet timeouts</strong></a></font></td></tr><tr><td><blockquote>
273 <p>If you are using the NIO connector, you can set individual timeouts for your different comet connections.
274 To set a timeout, simply set a request attribute like the following code shows:
275 <div align="left"><table cellspacing="4" cellpadding="0" border="0"><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#ffffff" height="1"><pre>CometEvent event.... event.setTimeout(30*1000);</pre></td><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr></table></div> or
276 <div align="left"><table cellspacing="4" cellpadding="0" border="0"><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#ffffff" height="1"><pre>event.getHttpServletRequest().setAttribute("org.apache.tomcat.comet.timeout", new Integer(30 * 1000));</pre></td><td bgcolor="#023264" width="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr><tr><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td><td bgcolor="#023264" width="1" height="1"><img src="./images/void.gif" alt="" width="1" height="1" vspace="0" hspace="0" border="0"></td></tr></table></div>
277 This sets the timeout to 30 seconds.
278 Important note: in order to set this timeout, it has to be done on the <code>BEGIN</code> event.
279 The default value is <code>soTimeout</code>
280 </p>
281 <p>If you are using the APR connector, all Comet connections will have the same timeout value. It is <code>soTimeout*50</code>
282 </p>
283 </blockquote></td></tr></table>
284
285 </blockquote></td></tr></table><table border="0" cellspacing="0" cellpadding="2"><tr><td bgcolor="#525D76"><font color="#ffffff" face="arial,helvetica.sanserif"><a name="Asynchronous writes"><!--()--></a><a name="Asynchronous_writes"><strong>Asynchronous writes</strong></a></font></td></tr><tr><td><blockquote>
286
287 <p>
288 When APR or NIO is enabled, Tomcat supports using sendfile to send large static files.
289 These writes, as soon as the system load increases, will be performed
290 asynchronously in the most efficient way. Instead of sending a large response using
291 blocking writes, it is possible to write content to a static file, and write it
292 using a sendfile code. A caching valve could take advantage of this to cache the
293 response data in a file rather than store it in memory. Sendfile support is
294 available if the request attribute <code>org.apache.tomcat.sendfile.support</code>
295 is set to <code>Boolean.TRUE</code>.
296 </p>
297
298 <p>
299 Any servlet can instruct Tomcat to perform a sendfile call by setting the appropriate
300 request attributes. It is also necessary to correctly set the content length
301 for the response. When using sendfile, it is best to ensure that neither the
302 request or response have been wrapped, since as the response body will be sent later
303 by the connector itself, it cannot be filtered. Other than setting the 3 needed
304 request attributes, the servlet should not send any response data, but it may use
305 any method which will result in modifying the response header (like setting cookies).
306 </p>
307
308 <ul>
309 <li><code>org.apache.tomcat.sendfile.filename</code>: Canonical filename of the file which will be sent as
310 a String</li>
311 <li><code>org.apache.tomcat.sendfile.start</code>: Start offset as a Long</li>
312 <li><code>org.apache.tomcat.sendfile.end</code>: End offset as a Long</li>
313 </ul>
314
315 </blockquote></td></tr></table></td></tr><!--FOOTER SEPARATOR--><tr><td colspan="2"><hr noshade="noshade" size="1"></td></tr><!--PAGE FOOTER--><tr><td colspan="2"><div align="center"><font color="#525D76" size="-1"><em>
316 Copyright &copy; 1999-2014, Apache Software Foundation
317 </em></font></div></td></tr></table></body></html>