Detect client disconnect in Server Sent Events in Java - java

I have SSE rest application, and am using PrintWriter to flush the data to the client. I do use PrintWriter checkError() method to determine client is available or not, but it does not report error when client connection (Wi-Fi) goes away, and still thinks client is still connected.
Is there a way in Server Sent Events using Java API which I could leverage to figure out client has been disconnected in case of Half open connections, so that I could close that streaming channel.

Related

Jersey/Servlet Serverside handling of network failures

-- EDIT: --
To rephrase the question.
Does HTTP know anything about the status of underlying TCP connection?
TCP is a reliable protocol. When the server sends data to the client it expects an acknowledgment signal from that client. What happens in HTTP when the underlying server side TCP connection fails to receive the ACK signal?
-- ORIGINAL Question: --
I am trying to solve a design issue on our HTTP client/server app.
Here is the situation:
The server runs on Tomcat, and we are somewhat limited to using Jersey or Servlets for the server side implementation.
The client requests data from the Server, which once read is deleted.
Data must not be deleted if the client has not received it.
There is no confirmation from the client if the data is received or not.
The client impl cannot be changed in any way.
The network connection is unstable and can be interrupted for long periods of time (e.g. 30 sec.) and also often.
The problem: if the client made a request and shortly after lost connection to the server, the server will not recognize this and it will delete and send the data to the client over the dead connection.
Ideally, we want to get an IOException when flushing the data stream to the client and handle it accordingly:
try (ServletOutputStream outputStream = httpServletResponse.getOutputStream()) {
outputStream.write(bytes);
outputStream.flush();
} catch (Exception e) {
// TODO: do something ...
}
I simulated this locally by killing the client shortly after sending the request or by setting a very low client read timeout value. In both cases I got a server side exception (with bioth Jersey and Servlets).
The last test was sending a request over a network and pulling the network cable in the process.
Unfortunately I did not get the expected result. The server streamed the data back without recognizing the interrupted connection.
So, does anyone have an idea how to force a Server side exception when the connection to the client is broken?
Any other ideas that don't involve using Sockets or confirmation calls from the client?
Thanks in advance!
Instead of deleting the file in real time, you can write a message on a queue in order to delete it later. The delete would have to check a database where you write if the client received the file completely.
I don't think there's a way to know for certain whether the data arrived to the client unless the client sends an acknowledgement message.
The only solution seems to be not actually deleting the data, but keeping it and setting a 'deleted' flag. But since I don't know the particular use case, I'm not sure if this helps...
TCP is a two way protocol.
If you set up an input stream and call InputStream.read(), this should return -1 if the client has disconnected.
More detail here:
Java Sockets: check if client is able to receive message from server

Delay when closing Tyrus WebSocket Sessions

I'm building a service with Tyrus in Standalone Mode (Grizzly Server) where I send huge amounts of binary data via WS to a client. In my setup, the service is located behind a proxy server, so all data that is send, is first buffered at the proxy and after the proxy in the unix send buffer.
At a certain point in this transfer, I want to serverside close the connection. When i do so, the client gets the onClose event as soon as all the data waiting in the buffer and proxy is sent.
This behavior, where all messages are handled sequentiell and therefore the close message is the last one recieved by the client, is understandable.
But what I need is a way to close the WebSocket connection in realtime. Like the underlying TCP connection would close and therefor the client won't ever get the remaining data stored in the send buffer and proxy.
Does anyone got an idea how to create such an behavior with the Tyrus API?

How to disconnect a socket once the socket.emit is done

I am using socket.io-java-client for connecting my java class on the server side to node.js and emit some events.
since I am running this on the server I dont want the socket thread to be running always.
As soon as my emit is done I want to disconnect the socket.
I tried
SocketIO socket=new SocketIO("http://IP:9001");
socket.emit("EVENT", "data");
socket.disconnect();
but this fails because we are closing the socket even before it has sent the message.
Is there any handler for emit success? How can I close the socket after the emit is successful?
After you've sent message to server, server can drop connection from its side. Just on event of receiving specific message it simply can disconnect that client socket.
Or server can additionally send response and client can close him self on receiving this response. But server should secure him self creating timeout in order to close idle clients who did not closed them self.
I recommend to do this operation on server side, and do not ever trust client side with such decisions.
Client can do it additionally after some timeout.
If you use Socket.IO just to send one message and close it after message sent, then there is no point to use Socket.IO as it will have overhead based on handshaking process, and you might consider using just HTTP request in order to send single messages to server.

Why does DefaultHttpClient send data over a half-closed socket?

I'm using DefaultHttpClient with a ThreadSafeClientConnManager on Android (2.3.x) to send HTTP requests to a my REST server (embedded Jetty).
After ~200 seconds of idle time, the server closes the TCP connection with a [FIN]. The Android client responds with an [ACK]. This should and does leave the socket in a half-closed state (server is still listening, but can't send data).
I would expect that when the client tries to use that connection again (via HttpClient.execute), DefaultHttpClient would detect the half-closed state, close the socket on the client side (thus sending it's [FIN/ACK] to finalize the close), and open a new connection for the request. But, there's the rub.
Instead, it sends the new HTTP request over the half-closed socket. Only after sending is the half-closed state detected and the socket closed on the client-side (with the [FIN] sent to the server). Of course, the server can't respond to the request (it had already sent its [FIN]), so the client thinks the request failed and automatically retries via a new socket/connection.
The end result is that server sees and processes two copies of the request.
Any ideas on how to fix this? (My server does the correct thing with the second copy, but I'm annoyed that the payload is transmitted twice.)
Shouldn't DefaultHttpClient detect that the socket was closed when it first tries to write the new HTTP packet, close that socket immediately, and start a new one? I'm baffled as to how a new HTTP request is sent on a socket minutes after the server sent a [FIN].
This is a general limitation of the blocking I/O in Java. There is simply no way of finding out whether or not the opposite endpoint has closed connection other than by attempting to read from the socket. Apache HttpClient works this problem around by employing the so stale connection check which is essentially a very brief read operation. However, the check can and often is disabled. In fact it is often advisable to have it disabled due to extra latency the check introduces. I have no idea how exactly the version of HttpClient shipped with Android behaves in this regard but you could try explicitly enabling the check by using an appropriate config parameter.
A better solution to this problem might be evicting connections from the connection pool that have been idle over a particular period of time (say 150 seconds) after a period of inactivity.
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e652

Netty - Does closing the socket at the client end close the channel at the server

My TCP server is implemented using Netty. My client using vanilla java.net.Socket to connect to this server. I'm using the same socket to send multiple requests to the server. Once done with all the requests the client calls socket.close().
I'm not closing the channel anywhere in my server code. Also, I've set TCP KEEP_ALIVE on my server. Will closing the socket on the client end automatically close the channel on the server or do I've to do something else explicitly and what is the best practice ?
Usually, if an application closes a socket, its remote peer also notices that the closure. Therefore, you don't need to call close() on both side. However, sometimes, due to network problems, you might not get notified when the remote peer closes the connection. To work around this problem, it's a good idea to send some message periodically, and then you will detect the unexpected closure sooner.
Please note SO_KEEP_ALIVE will not help much here because for most operating systems because the default keep alive time is very long.

Categories