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?
Related
I have a Spring Boot application with an endpoint, that returns a org.springframework.web.servlet.mvc.method.annotation.SseEmitter.
Multiple clients connect to my backend and their SseEmitters get stored (in memory), so that they can send each other messages via another endpoint, which the server then forwards to all connected emitters.
My problem is, that the SseEmitter class only has onCompletion, onError and onTimeout events. Neither of them gets called when a client simply disconnects.
Is there a way to see when a connection gets disconnected? Or maybe a way to get the underlying socket and listen for it to close or something?
-- 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
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.
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.
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.