-- 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
Related
I have classic http client/server application where the server serves the clients data at their will but also performs some kind of call-backs to the list of clients' addresses it has. My two questions are :
1- How would the server know if a client is down (the client did not disconnect but the connection got suddenly interrupted) ?
2- Is there a way to know from the server-side if the process at client-side listening on the call-back port is still up (i.e. client call-back socket is still open) ?
1- How would the server know if a client is down (the client did not disconnect but the connection got suddenly interrupted) ?
Option #1: direct communication
Client tells server "I'm alive" at a periodic interval. You could make your client to ping your server at a configurable interval, and if the server does not receive the signal for a certain time, it'll mark the client as down. Client could even tell server more info(e.g. It's status) in each heartbeat if necessary, this is also the way used in many distributed systems(e.g. Hadoop/Hbase).
Option #2: distributed coordination service
You could treat all clients connected to a server as a group, and use a 3rd party distributed coordination service like Zookeeper to facilitate the membership management. Client registers itself to Zookeeper as a new member of the group right after booting up, and leaves the group if it's down. Zookeeper notifies the server whenever the membership changes.
2- Is there a way to know from the server-side if the process at client-side listening on the call-back port is still up (i.e. client call-back socket is still open) ?
I think this can only be done by the way Option #1 listed above. It could be either the way clients tell server "My callback port is OK" at a fixed interval, or the server asks clients "Are your callback port OK?" and wait its response at a fixed interval
You would have to establish some sort of protocol; and simply spoken: the server keeps track of "messages" that it tried to sent to clients.
If that "send" is acknowledged, fine; if not: then the server might do a limited number of retries; and then regard that client as "gone"; and then drop any other messages for that client.
1- How would the server know if a client is down (the client did not disconnect but the connection got suddenly interrupted) ?
A write to the client will fail.
2- Is there a way to know from the server-side if the process at client-side listening on the call-back port is still up (i.e. client call-back socket is still open
A write to the client will fail.
The write won't necessarily fail immediately, due to TCP buffering, but the write will eventually provoke retries and retry timeouts that will cause a subsequent read or write to fail.
In Java the failure will manifest itself as an IOException: connection reset.
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 will the server know of client connection loss? does this trigger an event? is this possible to store code (server side) so that it can execute before the connection loss happen?
This connection loss can happen if:
being idle for too long.
client side terminated.
etc.
This i am asking in particular to Jsp and php.
It depends on the protocol you're talking about, but a "connection" is typically established through a three-way handshake, which causes both parties to simply agree that they're "connected" now. This means both parties remember in a table that there's an open connection to IP a.b.c.d on port x and what context this "connection" is associated with. All incoming data from that "connection" is then passed to the associated context.
That's all there is to it, there's no real "physical" connection; it's just an agreed upon state between two parties.
Depending on the protocol, a connection can be formally terminated with an appropriate packet. One party sends this packet to the other, telling it that the "connection" is terminated; both parties remove the table entries and that's that.
If the connection is interrupted without this packet being sent, neither party will know about it. Only the next time one party tries to send data to the other will this problem become apparent.
Depending on the protocol a connection may automatically be considered stale and terminated if no data was received for a certain amount of time. In this case, a dead connection will be noticed sooner, but requires a constant back and forth of some sort between both parties.
So in short: yes, there is a server event that can be triggered, but it is not guaranteed to be triggered.
When you close a socket, the socket on the other end is notified. However, if the connection is lost ungracefully (e.g. a network cable is unplugged, or a computer loses power), then you probably will not find out.
To deal with this, you can send periodic messages just to check the connection. If the send fails, then the connection has been interrupted. Make sure you set up your sockets to only wait for a reasonable amount of time, though.
If you are talking about a typical client server architecture, server shouldn't bother about the connection to the client. Only client should bother about connection to server. Client should take measures to avoid the connection being dropped like periodically sending a keep alive message or similar to avoid timeout.
Why does server need to bother about connection loss/termination.
Server job is to serve the request which comes from the client. That's it. If client doesn't receive the data it expected from Server then it can take appropriate action. If connection gets disconnected when server is doing some processing for giving data to client; then also server can't do much as http request is initiated by client.
So client can make a new request if for some reason it didn't get response.
i have implemented file upload code which uses a secure socket to upload files to a server using content-type Multipart Form-data to write the bytes.
Now and again I get a bad socket id error which through analysis in wireshark tells me that a fin packet is being sent from the server to the client for some reason. The identical code uploads 80% of the time so I dont think it is a bad format error so why would the server be disconnecting the connection when the content type states that there is moe data to be sent?
Anyways, If i cant solve the bad socket id issue would tcp/socket connections allow for a reconnection to resume the upload where it left off before disconnection.
Looking forward to insights on to this matter.
Thank you
Are you calling flush on your socket? Sometimes you need to explicitly flush any remaining data otherwise "weird" behavior (i.e. not sending the last packet) can occur. Just an idea.
I have written a socket program in Java. Both server and client can sent/receive data to each other. But I found that if client sends data to server using TCP then internally TCP sends acknowledgement to the client once the data is received by the server. I want to detect or handle that acknowledgement. How can I read or write data in TCP so that I can handle TCP acknowledgement. Thanks.
This is simply not possible, even if you were programming in C directly against the native OS sockets API. One of the points of the sockets API is that it abstracts this away for you.
The sending and receiving of data at the TCP layer doesn't necessarily correlate with your Java calls to send or receive data. The data you send in one Java call may be broken into several pieces which may be buffered, sent and received independently, or even received out of order.
See here for more discussion about this.
Any data sent over a TCP socket is acknowledged in both directions. Data sent from client to server is the same as data sent from server to client as far as TCP wire communications and application signaling. As #Eric mentions, there is no way to get at that signaling.
It may be that you are talking about timing out while waiting for the response from the server. That you'd like to detect if a response is taking too long. Is it possible that the client's message is larger than the server's response so the buffering is getting in the way of the response but not the initial request? Have you tried to use non-blocking sockets?
You might want to take a look at the NIO code if you have not already done so. It has a number of classes that give you more fine grained control over socket communications.
This is not possible in pure Java since Java's network API all handles socket, which hides all the TCP details.
You need a protocol that can handle IP-layer data so you can get TCP headers. DLPI is the most popular API to do this,
http://www.opengroup.org/onlinepubs/9638599/chap1.htm
Unfortunately, there is not Java implementation of such network. You have to use native code through JNI to do this.
I want to detect or handle that acknowledgement.
There is no API for receiving or detecting the ACKs at any level above the protocol stack.
Rethink your requirement. Knowing that the data has got to the server isn't any use to an application. What you want to know is that the peer application has received it, in which case you have to get the peer application to acknowledge at the application protocol level.