On 01/11/2016 09:44, Bruce Huang wrote:
> Hi all,
> 
> We have a simple servlet which implements Apache CometEvent for long
> polling connection on tomcat8. It works well when we used
> org.apache.coyote.http11.Http11NioProtocol, however, we have now changed to
> using org.apache.coyote.http11.Http11Nio2Protocol and it will not work
> properly.
> 
> Tomcat: v8.0.23
> JDK: v1.8.0_45
> OS: Windows server 2008 R2

The first thing to do is to test the latest 8.0.x release.

Keep in mind that Comet is deprecated so if there is still a bug in
8.0.x, fixing it might not be a priority. Switching back to NIO may be a
better option.

Mark


> 
> The connector setting as below:
> 
> <Connector port="8443"
> protocol="org.apache.coyote.http11.Http11Nio2Protocol"
>    maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
>    clientAuth="false" sslProtocol="TLS" connectionTimeout="60000"
>    keystoreFile="D:\localhost.jks" keystorePass="******" />
> 
> The timeout of the event will not work as we have set it to 300 seconds(by
> event.setTimeout(300000)), the comet connection will be disconnected after
> 60 seconds which I believe is the connector connection timeout. And there
> will have thrown an exception as below
> 
> 28-Oct-2016 15:04:33.748 SEVERE [http-nio2-8443-exec-5]
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process Error
> reading request, ignored
> java.lang.IllegalStateException: Reading not allowed due to timeout or
> cancellation
>     at
> sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:249)
>     at
> sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:297)
>     at
> org.apache.tomcat.util.net.SecureNio2Channel.read(SecureNio2Channel.java:792)
>     at
> org.apache.tomcat.util.net.Nio2Endpoint.awaitBytes(Nio2Endpoint.java:871)
>     at
> org.apache.coyote.http11.Http11Nio2Protocol$Http11ConnectionHandler.release(Http11Nio2Protocol.java:180)
>     at
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:722)
>     at
> org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.doRun(Nio2Endpoint.java:1073)
>     at
> org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.run(Nio2Endpoint.java:1032)
>     at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
>     at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
>     at
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
>     at java.lang.Thread.run(Thread.java:745)
> 
> If the client makes the comet connection again after this, and the other
> client tries to send message. The comet will be END immediately and
> connection disconnected.
> 
> 
> The Connect servlet as below
> 
> public class Connect extends HttpServlet implements CometProcessor {
> 
>     ...
> 
>     public void event(CometEvent event) throws IOException,
> ServletException {
>         HttpServletRequest request = event.getHttpServletRequest();
>         HttpServletResponse response = event.getHttpServletResponse();
>         if (event.getEventType() == CometEvent.EventType.BEGIN) {
>             String deviceid = request.getParameter("id");
>             MessageSender.getInstance().addConnection(deviceid, event);
>             request.setAttribute("org.apache.tomcat.comet.timeout", 300 *
> 1000);
>             event.setTimeout(300 * 1000);
>         } else if (event.getEventType() == CometEvent.EventType.ERROR) {
>             MessageSender.getInstance().removeConnection(event);
>             event.close();
>         } else if (event.getEventType() == CometEvent.EventType.END) {
>             MessageSender.getInstance().removeConnection(event);
>             event.close();
>         } else if (event.getEventType() == CometEvent.EventType.READ) {
>             throw new UnsupportedOperationException("This servlet does not
> accept data");
>         }
>     }
> }
> 
> And we have another Trigger servlet for sending message to client:
> 
> public class Trigger extends HttpServlet {
>     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
>             throws ServletException, IOException {
>         byte[] receieveByteArray = ByteUtil.getHttpServletRequestBody(req);
>         sendTrigger(req, resp, receieveByteArray);
>     }
> 
>     private void sendTrigger(HttpServletRequest req, HttpServletResponse
> resp, byte[] trigger) throws IOException, ServletException
>     {
>         try
>         {
>             MessageSender.getInstance().sendTrigger(deviceId, trigger);
>         } catch (Exception e)
>         {
>             logger.error("Send trigger has thrown exception: ", e);
>         }
>     }
> }
> 
> And the MessageSender class as below
> 
> public class MessageSender
> {
>     private static final Map<String, CometEvent> connections = new
> ConcurrentHashMap<String, CometEvent>();
> 
>     public void addConnection(String deviceId, CometEvent event) {
>         connections.put(deviceId, event);
>     }
> 
>     public void removeConnection(CometEvent event) {
> 
>         while (connections.values().remove(event)) {
>     }
> 
>     public static MessageSender getInstance() {
>         return instance;
>     }
> 
>     public void sendTrigger(String deviceId, byte[] triggerMessage) throws
> IOException, ConnectionNotFoundException {
>         CometEvent comet = connections.get(deviceId);
>         HttpServletResponse response = comet.getHttpServletResponse();
>         response.addHeader("Content-Length",
> Integer.toString(triggerMessage.length));
>         response.addHeader("Content-Language", "en-US");
> 
>         ServletOutputStream servletOutputStream =
> response.getOutputStream();
>         servletOutputStream.write(triggerMessage);
>         servletOutputStream.flush();
>         servletOutputStream.close();
> 
>         comet.close(); // add for NIO2
>         connections.remove(deviceId);
>     }
> }
> 
> 
> Thanks,
> Bruce
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to