Hi Mark, > -----Original Message----- > From: Mark Thomas [mailto:ma...@apache.org] > Sent: Friday, October 4, 2013 11:58 PM > To: Tomcat Developers List > Subject: Re: 8.0.x / 7.0.x progress > > On 04/10/2013 22:49, Konstantin Preißer wrote: > > Hi Mark, > > > > while I was developing and experimenting with a WebSocket application > (that I think could be added to Tomcat 8's WebSocket examples), I think I > found some more possible issues with the Websocket handling. One of > these can be seen with the Snake example. > > > > > > A) For NIO and APR connector: > > It seems that when a client establishes a Websocket connection and then > stops to read data from it (but doesn't close the connection, so that writing > data to the underlying TCP connection will be blocked), and then after some > time continues to read data from the Websocket connection, then Tomcat > seems not to be able to read data from that client any more (and doesn't > notice when the connection has been closed), but it can still read from it. > > I think you have written read when you meant write somewhere in the > previous sentence.
Sorry, yes. I'll try again: It seems that when a client establishes a Websocket connection and then stops to read data from it (but doesn't close the connection, so that at Tomcat's side writing data to the underlying TCP connection will be blocked), and then after some time the client continues to read data from the Websocket connection, then Tomcat seems not to be able to read data from that client any more (and doesn't notice when the connection has been closed), but it can still write data to the client. > > To reproduce: > > 1) Start Tomcat (current trunk) on Windows 64-bit with Java7 64-bit and > either NIO or APR connector. > > 2) Open two instances of Firefox (that may or may not be on the same > machine) and open the snake example. On both instances, press up or down > key so that both snakes begin moving. > > 3) Suspend one of the two Firefox processes (say Firefox B). This can be > done with "Process Explorer" [1] tool by right-clicking on the firefox.exe > entry and select "Suspend". You can see that Firefox B does not respond any > more, but on Firefox A the snakes continue to move. > > 4) After some time, you can see that on Firefox A the snakes suddenly stop > moving. This is correct because the current code uses RemoteEndpoint.Basic > that may block on write() methods. > > 5) Now resume Firefox B with Process Explorer. You can see that on both > Firefoxes the snakes will continue to move. This means that both Firefoxes > are able to receive data from the Websocket connection. > > 6) When you try to change the direction of the snake in Firefox A, > everything works. However on Firefox B, the snake will not change its > direction. This means that while Tomcat continues to send data to this > Websocket connection, it cannot receive from it any more. > > 7) If you close Firefox B, then the corresponding snake will not disappear > (so it seems Tomcat doesn't notice that the connection closed). > > It would be worth taking a look with something like Wireshark to see if > the data is being sent to Tomcat. I have installed Wireshark now and can confirm that Firefox (after it is resumed) still sends data over the TCP connection which Tomcat seems not to be able to read. > > B) For BIO connector: > > I noticed that on Tomcat with BIO connector, when using a > RemoteEndpoint.Async to asynchronously send data over the WebSocket > connection, sendText(String, SendHandler) (or similar methods) will block if > the Remote endpoint does not read data from the connection, whereas for > NIO and APR connector this method will always return immediately. > > Is it intended that for the BIO connector those methods are blocking? As > the javadoc says, "Initiates the asynchronous transmission of a text message. > This method returns before the message is transmitted.", I would have > expected that e.g. another Thread is used to write in blocking mode, so that > the sendText() method can return immediately. > > You can't do non-blocking IO with the BIO connector. All communication > with BIO is blocking. This is working as designed. OK, but my understanding was that there is a difference between the terms "synchronous/asynchronous" and "blocking/non-blocking" (but maybe the meaning differs from programming language to programming language). For example, in .Net applications (C#) you can do Stream operations (read, write) in a synchronous and asynchronous mode, regardless of whether the underlying I/O supports NIO or only BIO. For asynchronous operations, you can specify a callback that is called (from another thread) when the operation has finished. When the underlying I/O supports NIO, an async operation will use NIO so that an additional thread is not required (only when the operation has completed, it will take an additional thread for the callback) . However, when the underlying I/O doesn't support NIO, then you can still do an asynchronous operation. E.g. if you do an async write(), then this seems to be done by using an additional thread (from a thread pool) that will use a blocking write(), and after that method returns, it calls your callback to inform you that the write operation has completed. (Of course, this has at least the same costs (Thread usage) as using synchronous writes if the I/O does not support NIO, but it will be transparent to the application if the underlying I/O uses BIO or NIO.) This is why I was excepting that RemoteEndpoint.Async#sendText(...) returns immediately, regardless of whether BIO or NIO is used. Regards, Konstantin Preißer --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org