title: Java Sockets and Dropped Connections
body: <p>What's the most appropriate way to detect if a socket has been dropped or not?  Or whether a packet did actually get sent?</p>
  
  <p>I have a library for sending Apple Push Notifications to iPhones through the Apple gatways (<a href="http://github.com/notnoop/java-apns" rel="noreferrer">available on GitHub</a>).  Clients need to open a socket and send a binary representation of each message; but unfortunately Apple doesn't return any acknowledgement whatsoever.  The connection can be reused to send multiple messages as well.  I'm using the simple Java Socket connections.  The relevant code is:</p>
  
  <pre><code>Socket socket = socket();   // returns an reused open socket, or a new one
  socket.getOutputStream().write(m.marshall());
  socket.getOutputStream().flush();
  logger.debug("Message \"{}\" sent", m);
  </code></pre>
  
  <p>In some cases, if a connection is dropped while a message is sent or right before; <code>Socket.getOutputStream().write()</code> finishes successfully though.  I expect it's due to the TCP window isn't exhausted yet.</p>
  
  <p>Is there a way that I can tell for sure whether a packet actually got in the network or not?  I experimented with the following two solutions:</p>
  
  <ol>
  <li><p>Insert an additional <code>socket.getInputStream().read()</code> operation with a 250ms timeout.  This forces a read operation that fails when the connection was dropped, but hangs otherwise for 250ms.</p></li>
  <li><p>set the TCP sending buffer size (e.g. <code>Socket.setSendBufferSize()</code>) to the message binary size.</p></li>
  </ol>
  
  <p>Both of the methods work, but they significantly degrade the quality of the service; throughput goes from a 100 messages/second to about 10 messages/second at most.</p>
  
  <p>Any suggestions?</p>
  
  <p>UPDATE:</p>
  
  <p>Challenged by multiple answers questioning the possibility of the described.  I constructed "unit" tests of the behavior I'm describing.  Check out the unit cases at <a href="http://gist.github.com/273786" rel="noreferrer">Gist 273786</a>.</p>
  
  <p>Both unit tests have two threads, a server and a client.  The server closes while the client is sending data without an IOException thrown anyway.  Here is the main method:</p>
  
  <pre><code>public static void main(String[] args) throws Throwable {
      final int PORT = 8005;
      final int FIRST_BUF_SIZE = 5;
  
      final Throwable[] errors = new Throwable[1];
      final Semaphore serverClosing = new Semaphore(0);
      final Semaphore messageFlushed = new Semaphore(0);
  
      class ServerThread extends Thread {
          public void run() {
              try {
                  ServerSocket ssocket = new ServerSocket(PORT);
                  Socket socket = ssocket.accept();
                  InputStream s = socket.getInputStream();
                  s.read(new byte[FIRST_BUF_SIZE]);
  
                  messageFlushed.acquire();
  
                  socket.close();
                  ssocket.close();
                  System.out.println("Closed socket");
  
                  serverClosing.release();
              } catch (Throwable e) {
                  errors[0] = e;
              }
          }
      }
  
      class ClientThread extends Thread {
          public void run() {
              try {
                  Socket socket = new Socket("localhost", PORT);
                  OutputStream st = socket.getOutputStream();
                  st.write(new byte[FIRST_BUF_SIZE]);
                  st.flush();
  
                  messageFlushed.release();
                  serverClosing.acquire(1);
  
                  System.out.println("writing new packets");
  
                  // sending more packets while server already
                  // closed connection
                  st.write(32);
                  st.flush();
                  st.close();
  
                  System.out.println("Sent");
              } catch (Throwable e) {
                  errors[0] = e;
              }
          }
      }
  
      Thread thread1 = new ServerThread();
      Thread thread2 = new ClientThread();
  
      thread1.start();
      thread2.start();
  
      thread1.join();
      thread2.join();
  
      if (errors[0] != null)
          throw errors[0];
      System.out.println("Run without any errors");
  }
  </code></pre>
  
  <p>[Incidentally, I also have a concurrency testing library, that makes the setup a bit better and clearer.  Checkout the sample at gist as well].</p>
  
  <p>When run I get the following output:</p>
  
  <pre><code>Closed socket
  writing new packets
  Finished writing
  Run without any errors
  </code></pre>