Take the 2-minute tour ×

I am using TCP in my application. I am facing data loss issue if even if close socket gracefully. Here is the two sample program to replicate scenario.

//TCP Sender program continuously sends data

public class TCPClient {

 public static void main(String[] args) throws UnknownHostException, IOException {
    Socket soc = new Socket("xx.xx.xx.xx",9999);
    OutputStream stream = soc.getOutputStream();
    int i=1 ;
    while(true) {

        System.out.println("Writing "+ i);
        try {
        } catch (InterruptedException e) {



// TCP Server/Receiver

  public class TCPServer2 {

    System.out.println("program started");
    ServerSocket serverSock = new ServerSocket(9999);
    Socket socket =serverSock.accept();
    System.out.println("client connected");
     InputStream stream = socket.getInputStream();
     InputStreamReader reader = null;
      reader = new InputStreamReader(stream);
      int n=0;
      int i=1;
      while (true) {
        try {
            n = reader.read();
            System.out.println("Msg No.: "+n);
        } catch (Exception e) {
        if(i==5) {
            System.out.println("closing socket");
            //client should get exception while sending 6th msg




Now Ideally TCPClient program should get exception while sending 6th message but it gets Exception while sending 7th message. Is there any way to avoid this data loss problem apart from using high level protocols and SO_LINGER(linger does helps in this program but it may cause data loss issue in several other scenarios)?
NB: This message loss issue occurs if we use two different windows machine. On the same machine it works fine.

share|improve this question
add comment

3 Answers

up vote 1 down vote accepted

client should get exception while sending 6th msg

Not at all. The sender will get an exception eventually, if he keeps sending, but because of TCP buffering at both the sender and receiver, and because TCP sends are asynchronous, it definitely won't happen on the next write after the peer closes. It will happen afterwards, after:

  1. TCP has decided to send its send buffer.
  2. TCP has detected an incoming RST response.
  3. the application next calls send().
share|improve this answer
"TCP has decided to send its send buffer." - Is there any way to force TCP to send data immediately in Java? –  Cooper Khan Jul 24 '13 at 6:21
@CooperKhan It is sending it, as fast as it can, subject to pacing delays and the Nagle algorithm. There is no flush operation and no need for one. –  EJP Jul 29 '13 at 5:28
add comment

Interesting problem. Perhaps try flushing the OutputStream after each client write.

share|improve this answer
flushing also does not help. –  Cooper Khan Jul 23 '13 at 7:42
I don't know how to add a comment to EJP's answer, but I was going to suggest java.net.Socket.setTcpNoDelay(true) –  Kafkaesque Jul 24 '13 at 6:46
setTcpNoDelay(true) also does not work –  Cooper Khan Jul 24 '13 at 9:07
add comment

EJP's answer describes why your current solution will not work.

As for an alternative, the only way to do what you want is to make the protocol bi-directinoal. in other words, you need to set up some sort of server acknowledgement of each message received. the "simple" way to do this is to have the server immediately ack each message received. more complex protocols could allow for some sort of periodic ack. even with this solution, there are still problem areas. for instance, the client may not receive an ack (if the socket closes prematurely) and therefore the server may see the same message twice. long story short, you need some sort of reliable message transfer protocol, and there is plenty of documentation for these already online.

share|improve this answer
add comment

Your Answer


