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

Reply via email to