org.eclipse.jetty.io.EofException of Jetty websocket - websocket

I utilize Jetty (9.4.1) websocket for 2 ways communication between client and server.
On Client side, the messages 'onerror' and 'onclose' of WebSocket are listened, so that when there is a problem, the client will make a
new connection.
On Server side, the 'OnError' and 'OnClose' messages also handled.
Then, sometimes I see server got an 'org.eclipse.jetty.io.EofException', 'OnError' and 'OnClose' of ServerEndpoint are invoked. But on the Client side, there is no 'onerror' or 'onclose' message is sent.
Therefore, in this case the Client is not aware of the websocket connection is closed already, still use that connection.
My questions are:
1. How can this EofException happen?
2. When this error happen, is the connection actually close or still open? Because I cannot duplicate this error programmatically, I cannot investigate to understand clearly.
3. How can I make Client aware of this exception, so that Client can reconnect and function properly?

Related

How to prevent websocket opening handshake timeout?

I am trying to make a connection to a socket.io session. The connection is easily established, however, if I am idle for a short duration I get this error in my console:
websocket.js:116 WebSocket connection to 'ws://localhost:3000/socket.io/?EIO=3&transport=websocket&sid=PwzuR5tNmPmZfj0UAAAB' failed: WebSocket opening handshake timed out
I tried fixing the issue by setting pingTimeout and pingInterval but to no avail. I am not sure how to fix this or what is causing this.
On a side note, I am trying to read and understand the socket.io docs and am still not clear about what ping and pong packets exactly are. Does the client have to manually interact with the socketio server in order for it to receive pong packets or will it still receive pongs if say the client interacts with an http server on the same host ?

Spring websockets + Amazon MQ limitations

We want to use spring websockets + STOMP + amazon MQ as a full featured message broker. We were trying to do benchmarking, to find out how many client websocket connections single tomcat node can handle. But it appears that we hit amazonMQ connection limit first. As per the aws documentation, amazonMQ has a limit of 1000 connections per node (as far as I understand we can ask support to increase the limit, but I doubt that it can be increased big time). So my questions is:
1) Am I correct in assuming that for every websocket connection from client to spring/tomcat server, a corresponding connection being opened from server to broker? Is this correct behavior or we're doning something wrong here/missing something?
2) What can be done here? I mean I don't think this is a good idea to create broker node per evry 1000 users..
According to https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.html your are doing everything right, and it is documented behavior.
Quote from javadoc:
For each new CONNECT message, an independent TCP connection to the broker is opened and used exclusively for all messages from the client that originated the CONNECT message. Messages from the same client are identified through the session id message header. Reversely, when the STOMP broker sends messages back on the TCP connection, those messages are enriched with the session id of the client and sent back downstream through the MessageChannel provided to the constructor.
As for a fix, you can write your own message broker relay, with tcp connection pooling.

Interpretation of SetWriteDeadline error

I am writing a websocket server in Go that broadcasts messages to clients. I use SetWriteDeadline on each send so that the broadcast loop doesn't get stuck.
My question is: how do I interpret an error from SetWriteDeadline? In particular, should I assume that there is something wrong with that particular client and unregister it? Or is it a server-side issue that happened to get triggered on this client?
After researching SetWriteDeadline, I found that the deadline is for putting the message on the TCP stack server-side, not for the client to receive the message. So perhaps a better way to phrase my question is this: is there a separate TCP stack for each websocket client (perhaps this is the thing that has size WriteBufferSize), or is this buffer shared between clients? In the former case it seems like I should unregister the client on a SetWriteDeadline error, but not in the latter case.
Websocket connections are independent of other websocket connections.
Websocket connections have an underlying network connection. These network connections are also independent of each other.
An error returned from SetWriteDeadline indicates a problem with that specific websocket connection or the websocket connection's underlying network connection.
Also note that Gorilla's SetWriteDeadline method never returns an error.

How reconnect from server to client

I'am able to detect when client disconnect from a server by this code:
self._session.socket.on("close", function() {
console.log("client disconnected");
}
But how can I try reconnect to the disconnected client?
You cannot connect from server to client as client isn't listening to the websocket, but just connecting (to the server).
However, you can put a code in your client to reconnect it at onclose (or just close) event. Generally this occurs by recreating the WebSocket object in the client with the correct parameters.
Something as:
function connect(){
var mywebsocket = new WebSocket("ws://(your url)");
// ... my callbacks and functions...
mywebsocket.onclose = connect; // or arguments.callee
}
connect();
Should work correctly. ;)
Good luck.
If the client got disconnected for some reason (internet connection disruption/server issues) it will automatically reconnect on its own. To see how many attempts have been made or the status have a look at http://docs.meteor.com/#meteor_status
Since version 0.6.3 if the internet was disconnected. As soon as the internet is back it will attempt to reconnect too.
To reconnect from your code somewhere you can run Meteor.reconnect() from the client.
Unfortunately the meteor client can't listen for connections from the server so the server can't initiate a reconnection, you need some kind of connection to a server to send a message to the client to do something such as a reconnection.

How do i know if connection is alive with websockets?

I have a webapp, which is running in a browser. That webapp is connected to a server, which uses websockets. So the communication between the server and my client/browser is based on websockets. If some magic event occurs on the server, some webservice sends a new XML / JSON to my webapp and the new data gets displayed.
But how do i, as the client / browser, know if the connection is stil alive? Lets say i do not get any new XML for about 30 seconds. How would i know if the connection is closed/broken/server offline or everything is fine, but on the server himself no new magic event occured.
A websocket connection object has a readyState field which will tell you if the connection is still active (from the dart documentation). The readyState can be either
0 - connection not yet established
1 - conncetion established
2 - in closing handshake
3 - connection closed or could not open
You can also define an event handler for the websocket close event if this is something you'd like to handle (try to reconnect, etc).
3 ways:
rely on TCP to detect loss of connectivity, which will ultimately pop up in JS onclose event
send WebSocket pings from server .. browsers will reply with WS pongs, loss of connectivity is probably more robustly detected also on client side
send app level heartbeats from browser to server, server need to have logic to reply. you can't trigger WS pings from browsers (in JS)

Resources