Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do Java TCP/IP sockets report transmission success or failure to the application?

I am having a problem with Java TCP/IP sockets: my Java application will continue endlessly to send data to a server even if the server gets switched off (without a proper TCP/IP disconnect) in the meantime.

I am using the following code to send the data:

PrintWriter out = PrintWriter(socket.getOutputStream(), true);
out.write("text");

if (out.checkError()) {
   System.err.println("Error sending string!");
}

In another Stack Overflow question, I found the following answer:

TCP/IP (and therefor java sockets) will guarantee that you either successfully send the data OR get an error (exception in the case of java) eventually.

Is my code sufficient for getting informed about the TCP/IP stack not being able to successfully send my string or do I need to do something additionally?

Btw: was it correct to open a new question even though the other question was similar? It did not answer my question satisfactorily and I was only able to add a new answer, not a new comment.

like image 726
tajmahal Avatar asked May 20 '11 08:05

tajmahal


2 Answers

You might have two problems: PrintWriter is a strange beast in the Java Stream/Reader/Writer world in that it swallows exceptions and requires you to explicitly check for errors.

The only use for this (in my opinion) are the standard streams (System.out and System.err), where failure to write output should not halt the application (for example if no standard output is available).

Replace that with an OutputStreamWriter and you'll be informed about errors as soon as Java knows about them.

That brings me to the second possible problem: TCP/IP doesn't have any automated keep-alive packets: so if your connection gets severed in some way, you won't actually notice it until you attempt to send data.

So if you connect to some socket, send some packets, wait a bit and then get disconnected, you will only be notified of the fact when you next try to send some data. This is inherent in the TCP/IP protocol and not the fault of Java.

If you want to reduce the problem, then you could send periodic keep-alive/ping messages with no actual effect, except that they check if the connection is still alive.

like image 76
Joachim Sauer Avatar answered Oct 18 '22 01:10

Joachim Sauer


Your question is different enough I'd say. Google has a lot to say about this sort of thing though. The keep-alives (SO_KEEPALIVE) are not designed for this sort of thing. From what I have read the TCP spec says that they should not be sent more than once every two hours and it is up to your OS to manage it so you don't have much control. I emphasize from what I have read.

Whether you can use them more than once every two hours doesn't matter in your case though since you are continually sending data. Keep-alives are only needed if you want to detect a broken connection while you are not sending data.

If you were using the OutputStream of the Socket directly, it would throw an exception when you attempt to send to an unavailable destination (for whatever reason that may be). Since you are using PrintWriter, you need to check for errors manually using checkError().

So, in summary: Yes, it is sufficient for your purpose.

like image 38
Gyan aka Gary Buyn Avatar answered Oct 18 '22 01:10

Gyan aka Gary Buyn