3
votes

This is maybe more of a thing for discussion than a question.

Background:
I have two pairs of server/client, one pair written in Java and one written in C#. Both pairs are doing the same thing. No problems when I am using Java\Java and C#\C# combination. I would like to make combinations of Java\C# and C#\Java work as well. No problem with I\O, I am using byte array representing XML formatted string. I am bound to use TCP.

I need to care about graceful disconnect, in Java there is no such thing. When you close socket of client, server side socket remains in passive close state - therefore the server thread handling this socket is still alive, and in case of many clients I could end up with thousands of unnecessary threads. In C# it is enough to call TcpClient.Available to determine, whether there are data in buffer or whether the client has been closed(SocketException). In Java I could think of two approaches:

  1. you have to write something to the underlying stream of socket to really test, whether the other side is still opened or not.
  2. you have to make the other side aware, that you are closing one side of connection before you close it. I have implemented this one, before closing client socket I am sending packet containing 0x04 byte(end of transmission) to server, and server reacts on this byte by closing the server side of socket.

Unfortunatelly, both approaches have caused me a dilemma when it comes to C#\Java and Java\C# pairs of client\server. If I want these pairs to be able to communicate with each other, I will have to add code for sending the 0x04 byte to the C# client, and of course code handling it to C# server, which is kind of overhead. But I could live with unnecessary network traffic, main problem is, that this C# code is part of core communication library which I do not want to touch unless it is absolutely necessary

Question:
Is there other approach in Java to gracefully disconnect, which does not require writing to underlying stream of socket and checking the result so I do not have to handle this in C# code as well? I have a free hand when it comes to used libraries, I do not have to use only Java SE\EE.

2
What kind of I/O do you use in Java? NIO (i.e. Channels)? Or the old ones? Can you show a tiddly bit of (java) code? - Fildor
old java.io - Socket and ServerSocket. There is no problem with communication, I am able to freely send messages from client to server and back. I just wanted to know, if I have to handle the graceful disconnect in C# code as well in case that I want these mixed up pairs to work together. - Jan Hruby
Hm, I thought it would throw a SocketException if you call getOutput/InputStream on a closed socket. Do you have SocketTimeout value set to anything? - Fildor
I cannot use timeout, because I simply do not know, when some data from client arrives. It can be dormant for a long period of time and then send something. This is contract by the original C# server\client pair which I am rewriting to Java and cannot(should not) change. - Jan Hruby
Well I can remember that I did this once with timeout and a loop around the read, ignoring SocketTimeoutException. That way you can getOutputStream regularly from the socket instance and react on SocketException when that sould fail for the socket being closed by peer. - Fildor

2 Answers

2
votes

I have given (what I think is a) concise explanation on this "graceful disconnection" topic in this answer, I hope you find it useful.

Remember that both sides have to use the same graceful disconnection pattern. I have found myself trying to gracefully disconnect a Client socket but the Server kept sending data (did not shutdown its own side), which resulted in an infinite loop...

0
votes

the answer was apparent. There is nothing like graceful disconnect in C# as well, it is about TCP protocol contract. so there is same problem as in Java, with one slight difference, you can workaround on certain circumstances -> if you send 0 bytes through NetworkStream and then check TcpClient.Connected state, it is somehow correct. However from what I have found on the internet this is neither reliable nor preffered way how to test connection in C#. Of course in my C# library it has been used. In Java you cannot use this at all.

So my solution with sending "end of transmission" packet to server when client disconnects is solid, I have introduced it in C# library as well. Now I just tremble in fear for the first bug to emerge...

last point, I have to implement also some kind of mechanism that would collect handling threads on server for crashed clients. Keep that in mind if you are doing similar thing, no client is bound to end expectedly;)