java - Why is it impossible, without attempting I/O, to detect that TCP socket was gracefully closed by peer? -


as follow recent question, wonder why impossible in java, without attempting reading/writing on tcp socket, detect socket has been gracefully closed peer? seems case regardless of whether 1 uses pre-nio socket or nio socketchannel.

when peer gracefully closes tcp connection, tcp stacks on both sides of connection know fact. server-side (the 1 initiates shutdown) ends in state fin_wait2, whereas client-side (the 1 not explicitly respond shutdown) ends in state close_wait. why isn't there method in socket or socketchannel can query tcp stack see whether underlying tcp connection has been terminated? tcp stack doesn't provide such status information? or design decision avoid costly call kernel?

with of users have posted answers question, think see issue might coming from. side doesn't explicitly close connection ends in tcp state close_wait meaning connection in process of shutting down , waits side issue own close operation. suppose it's fair enough isconnected returns true , isclosed returns false, why isn't there isclosing?

below test classes use pre-nio sockets. identical results obtained using nio.

import java.net.serversocket; import java.net.socket;  public class myserver {   public static void main(string[] args) throws exception {     final serversocket ss = new serversocket(12345);     final socket cs = ss.accept();     system.out.println("accepted connection");     thread.sleep(5000);     cs.close();     system.out.println("closed connection");     ss.close();     thread.sleep(100000);   } }   import java.net.socket;  public class myclient {   public static void main(string[] args) throws exception {     final socket s = new socket("localhost", 12345);     (int = 0; < 10; i++) {       system.out.println("connected: " + s.isconnected() +          ", closed: " + s.isclosed());       thread.sleep(1000);     }     thread.sleep(100000);   } } 

when test client connects test server output remains unchanged after server initiates shutdown of connection:

connected: true, closed: false connected: true, closed: false ... 

i have been using sockets often, selectors, , though not network osi expert, understanding, calling shutdownoutput() on socket sends on network (fin) wakes selector on other side (same behaviour in c language). here have detection: detecting read operation fail when try it.

in code give, closing socket shutdown both input , output streams, without possibilities of reading data might available, therefore loosing them. java socket.close() method performs "graceful" disconnection (opposite thought) in data left in output stream sent followed fin signal close. fin ack'd other side, regular packet would1.

if need wait other side close socket, need wait fin. , achieve that, have to detect socket.getinputstream().read() < 0, means should not close socket, close inputstream.

from did in c, , in java, achieving such synchronized close should done this:

  1. shutdown socket output (sends fin on other end, last thing ever sent socket). input still open can read() , detect remote close()
  2. read socket inputstream until receive reply-fin other end (as detect fin, go through same graceful diconnection process). important on os don't close socket long 1 of buffer still contains data. they're called "ghost" socket , use descriptor numbers in os (that might not issue anymore modern os)
  3. close socket (by either calling socket.close() or closing inputstream or outputstream)

as shown in following java snippet:

public void synchronizedclose(socket sok) {     inputstream = sok.getinputstream();     sok.shutdownoutput(); // sends 'fin' on network     while (is.read() > 0) ; // "read()" returns '-1' when 'fin' reached     sok.close(); // or is.close(); can close socket } 

of course both sides have to use same way of closing, or sending part might sending enough data keep while loop busy (e.g. if sending part sending data , never reading detect connection termination. clumsy, might not have control on that).

as @warrendew pointed out in comment, discarding data in program (application layer) induces non-graceful disconnection @ application layer: though data received @ tcp layer (the while loop), discarded.

1: "fundamental networking in java": see fig. 3.3 p.45, , whole §3.7, pp 43-48


Comments

Popular posts from this blog

c++ - How do I get a multi line tooltip in MFC -

asp.net - In javascript how to find the height and width -

c# - DataTable to EnumerableRowCollection -