This article covers the following topics:
 To ensure orderly or graceful release of TCP connections is a challenge with 
  TCP networking applications. Abortive or ungraceful release may result if special 
  care is not taken. In Java, an unexpected abortive release can manifest itself 
  by the application receiving a java.net.SocketException when reading 
  or writing to the socket. read() and write() normally 
  return a numeric value indicating, respectively, the number of bytes received 
  or sent. If an exception is received instead, this indicates the connection 
  has been aborted and also that data may have been lost or discarded. This article 
  explains what causes socket connections to be aborted and provides tips for 
  avoiding the situation, except for the case where an application intends to 
  abort the connection.
First, we need to distinguish the differences between an abortive and an orderly 
  connection release. To understand this distinction we need to look at what happens 
  at the TCP protocol level. It is helpful to imagine an established TCP connection 
  as actually two separate, semi-independent streams of data. If the two peers 
  are A and B, then one stream delivers data from A to B, and the other stream 
  from B to A. An orderly release occurs in two stages. First one side (say A) 
  decides to stop sending data and sends a FIN message across to 
  B. When the TCP stack at B's side receives the FIN it knows that 
  no more data is coming from A, and whenever B reads all preceding data off the 
  socket, further reads will return the value -1 to indicate end-of-file. 
  This procedure is known as the TCP half-close, because only one half of the 
  connection is closed. Not surprisingly, the procedure for the other half is 
  exactly the same. B sends a FIN message to A, who eventually receives 
  a -1 after reading all preceding data sent by A off the socket.
By contrast, an abortive close uses the RST (Reset) message. If either side issues an RST, this means the entire connection is aborted and the TCP stack can throw away any queued data which has not been sent or received by either application.
So, how do Java applications perform orderly and abortive releases? Let's consider 
  abortive releases first. A convention that has existed since the days of the 
  original BSD sockets is that the "linger" socket option can be used 
  to force an abortive connection release. Either application can call Socket.setLinger 
  (true, 0) to tell the TCP stack that when this socket is closed, the abortive 
  (RST) procedure is to be used. Setting the linger option has no immediate effect, 
  except that when Socket.close() is called subsequently, the connection 
  is aborted with an RST message. As we will see shortly, there are other ways 
  that may cause a connection to be aborted, but this is the simplest way to make 
  it happen.
The close() method is also used to perform orderly release, as 
  well as abortive. So, at its simplest, the difference between an orderly release 
  and an abortive release could be as little as not setting the linger(0) option, 
  described above, prior to calling Socket.close(). Take the example 
  of two connected peers A and B: If A calls Socket.close(), a FIN 
  message is sent from A to B; and when B calls Socket.close(), a 
  FIN is sent from B to A. In fact, the default setting for the linger 
  option is to not use abortive close; so if two applications terminate their 
  connection just by using Socket.close(), then the outcome should 
  be an orderly release. So what, then, is the problem?
The problem is a slight mismatch between the semantics of Socket.close() 
  and the TCP FIN message. Sending a TCP FIN message 
  means "I am finished sending", whereas Socket.close() 
  means "I am finished sending and receiving." When you call Socket.close(), 
  clearly it is no longer possible to send data; nor, however, is it possible 
  to receive data. So what happens, for example, when A attempts an orderly release 
  by closing the socket, but B continues to send data? This is perfectly allowable 
  in the TCP specification, because as far as TCP is concerned only one half of 
  the connection has been closed. But since A's socket is closed there is nobody 
  to read data if B should continue sending. In this situation A's TCP stack must 
  send an RST to forcibly terminate the connection.
Another common scenario, which may result in an unintended SocketException, 
  is the following: Say A has sent data to B, but B closes the socket without 
  reading all the data. In this situation, B's TCP stack knows that some data 
  is effectively lost and it will forcibly terminate with RST rather than use 
  the orderly FIN procedure. A will get a SocketException 
  if it then tries to send or receive data from the socket.
There are a number of simple ways to avoid being surprised by this problem.
shutdownOutput(). This method has the same effect as close() 
    in that a FIN is sent to indicate that this peer has finished 
    sending, but it is still possible to read from the socket until such time 
    as the remote peer sends a FIN and end-of-file is read from the 
    stream. Then the socket can be closed with Socket.close().