Hi all,
while working on the Drawboard Websocket example that is included in Tomcat, I
found some things in Tomcat's implementation / the Websocket Spec which I'm not
clear about.
1) How to asynchronously close / abort a Websocket session?
For the Drawboard, I'm using the RemoteEndpoint.Async to send messages
asynchronously (that is, the sendText(String, SendHandler) will return
immediately and when sending is finished, SendHandler.onResult() will be
called).
Now, there may be a situation where I want to abort a Websocket session while
async send has not yet finished, or asynchronously close it so that a close()
method does not block.
The only way to close a websocket normally (not aborting) seems to be by
calling Session.close(). However, this method will block if the remote endpoint
does not read data, and it seems there is no async close() method that returns
immediately (just like Async.sendText()) even if the closing handshake is
waiting to be sent on the TCP connection.
The problem with the Drawboard example is that it needs to be able to
abort/close Websocket sessions if the client does not read data from the TCP
connection, to avoid buffering outgoing messages endlessly. Currently, I'm just
calling session.close() (while async sending has not yet finished), but as this
method may block, it temporarily stops processing of messages from other
clients.
(For example, in .Net there is a CloseAsync()/CloseOutputAsync method of the
WebSocket class that asynchronously sends the closing handshake, and an Abort()
method that immediately aborts the Websocket/TCP connection and cancels all
pending I/O operations. Ideally, I would need something like this Abort()
method for immediately aborting the Websocket session).
2) It seems that when using RemoteEndpoint.Basic to send data synchronously and
the remote endpoint does not read from the TCP connection, then a
TimeoutException (wrapped in IOException) is thrown several seconds after
calling send(). However, when using RemoteEndpoint.Async to send data
asynchronously, this is not the case - the SendHandler is not called until the
remote endpoint continues to read data. Is there some configuration to set a
Timeout for async sending?
3) It seems that session.close() will call the onClose method of the Endpoint,
even if this was called inside of another event handling method like onMessage.
E.g. if you do something like this in an Endpoint subclass:
@Override
public void onMessage(String message, boolean last) {
session.close();
}
then Endpoint.onClose(..) will be called directly from session.close() (it will
be called before onMessage(...) returns). This can be a bit confusing, because
e.g. in Javascript, if you call ws.close() inside of the onmessage handler,
then the onclose handler will be called after the onmessage handler returns.
Is this behavior required by the spec? (E.g. JSR 356 spec says at point 4.5
@OnClose:
"The annotation defines that the decorated method be called whenever a remote
peer
is about to be disconnected from this endpoint, whether that process is
initiated by the remote peer, by
the local container or by a call to session.close(). The container notifies the
method before the connection
is brought down [WSC-4.5-1]."
If the last sentence is to be interpreted that the Websocket closing handshake
must not be sent until onClose() was called, this would explain it, although
that would seem a bit strange to me.
Thanks!
Regards,
Konstantin Preißer
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]