title: Java - Write call to socket output stream blocking in full duplex
body: <p>I'm writing a client server application and I want to both read and write on one socket from two different threads (one thread for reading, one for writing). I have the system nearly working, but there is one perplexing bug that I can't seem to wrap my head around. Reading and writing work perfect independent of each other, but when I start reading from the <code>Socket</code>'s <code>OutputStream</code> in one thread, all calls to write to the <code>InputStream</code> in a different thread block indefinitely.</p>
  
  <p>I've written a small test program for quickly reproducing the issue and to eliminate as many external variables as I could. I use <code>java.nio</code>'s <code>ServerSocketChannel</code> and <code>SocketChannel</code> to set up the connection and I use <code>java.io</code>'s <code>Socket</code> (the underlying socket of a <code>SocketChannel</code>) for its ease of use with <code>ObjectInputStream</code> and <code>ObjectOutputStream</code>. The test program is designed to run twice; for the first run, the user inputs <code>s</code> to launch the server and on the second run the user inputs <code>c</code> to run the client.</p>
  
  <p><b>My question is:</b> Why does execution of the below program block on the second call to <code>objectOutput.writeObject( message );</code> in the <code>server()</code> method? (fourth to last line in that method)</p>
  
  <p>I've included the expected outputs and actual outputs and what I think they mean below the program code.</p>
  
  <pre><code>import java.io.IOException;
  import java.io.ObjectInput;
  import java.io.ObjectInputStream;
  import java.io.ObjectOutput;
  import java.io.ObjectOutputStream;
  import java.io.Serializable;
  import java.net.InetSocketAddress;
  import java.net.Socket;
  import java.nio.channels.ServerSocketChannel;
  import java.nio.channels.SocketChannel;
  import java.util.Scanner;
  
  public class Main {
  
      private static final String IP_ADDRESS = "localhost";
      private static final int WELL_KNOWN_PORT = 4000;
  
      public static void main( String... args ) throws Exception {
          Scanner scanner = new Scanner( System.in );
          System.out.print( "choose (s)erver or (c)lient: " );
          char choice = scanner.nextLine().charAt( 0 );
          switch ( choice ) {
          case 's':
              server();
              break;
          case 'c':
              client();
              break;
          default:
              break;
          }
          scanner.close();
      }
  
      private static void server() throws Exception {
  
          // initialize connection
  
          ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
          serverSocketChannel.bind( new InetSocketAddress( WELL_KNOWN_PORT ) );
          System.out.println( "waiting for client to connect" );
          SocketChannel socketChannel = serverSocketChannel.accept();
          System.out.println( "client connected" );
          socketChannel.configureBlocking( true );
          while ( !socketChannel.finishConnect() )
              Thread.sleep( 100 );
          Socket socket = socketChannel.socket();
          ObjectOutput objectOutput = new ObjectOutputStream( socket.getOutputStream() );
  
          // write first object to stream
  
          Message message = new Message( 1 );
          System.out.println( "writing first object to object output stream: " + message );
          objectOutput.writeObject( message );
          System.out.println( "first object written to object output stream" );
          objectOutput.flush();
          System.out.println( "object output stream flushed" );
  
          // start reading in a separate thread
  
          new Thread( () -&gt; {
              ObjectInput objectInput = null;
              try {
                  objectInput = new ObjectInputStream( socket.getInputStream() );
              } catch ( IOException e ) {
                  e.printStackTrace();
              }
              Message messageIn = null;
              try {
                  System.out.println( "reading on object input stream" );
                  messageIn = (Message) objectInput.readObject();
                  System.out.println( "read object on object input stream: " + messageIn );
              } catch ( ClassNotFoundException | IOException e ) {
                  e.printStackTrace();
              }
              System.out.println( messageIn );
          } ).start();
          Thread.sleep( 100 ); // allow time for object listening to start
  
          // write second object to stream
  
          message = new Message( 2 );
          System.out.println( "writing second object to object output stream: " + message );
          objectOutput.writeObject( message ); // this call seems to block??
          System.out.println( "second object written to object output stream" );
          objectOutput.flush();
          System.out.println( "object output stream flushed" );
      }
  
      private static void client() throws Exception {
  
          // initialize connection
  
          SocketChannel socketChannel = SocketChannel.open();
          socketChannel.configureBlocking( true );
          socketChannel.connect( new InetSocketAddress( IP_ADDRESS, WELL_KNOWN_PORT ) );
          while ( !socketChannel.finishConnect() )
              Thread.sleep( 100 );
          Socket socket = socketChannel.socket();
          ObjectOutput objectOutput = new ObjectOutputStream( socket.getOutputStream() );
          ObjectInput objectInput = new ObjectInputStream( socket.getInputStream() );
  
          // read first object
  
          System.out.println( "reading first object on object input stream" );
          Message message = (Message) objectInput.readObject();
          System.out.println( "read first object on object input stream: " + message );
  
          // read second object
  
          System.out.println( "reading second object on object input stream" );
          message = (Message) objectInput.readObject();
          System.out.println( "read second object on object input stream: " + message );
  
          // write confirmation message
  
          message = new Message( 42 );
          System.out.println( "writing confirmation message to object output stream: " + message );
          objectOutput.writeObject( message );
          System.out.println( "confirmation message written to object output stream" );
          objectOutput.flush();
          System.out.println( "object output stream flushed" );
      }
  
      private static class Message implements Serializable {
  
          private static final long serialVersionUID = 5649798518404142034L;
          private int data;
  
          public Message( int data ) {
              this.data = data;
          }
  
          @Override
          public String toString() {
              return "" + data;
          }
      }
  }
  </code></pre>
  
  <p><b>Server</b></p>
  
  <p>Expected output:  </p>
  
  <pre><code>choose (s)erver or (c)lient: s
  waiting for client to connect
  client connected
  writing first object to object output stream: 1
  first object written to object output stream
  object output stream flushed
  reading on object input stream
  writing second object to object output stream: 2
  second object written to object output stream
  object output stream flushed
  read object on object input stream: 42
  </code></pre>
  
  <p>Actual output: </p>
  
  <pre><code>choose (s)erver or (c)lient: s
  waiting for client to connect
  client connected
  writing first object to object output stream: 1
  first object written to object output stream
  object output stream flushed
  reading on object input stream
  writing second object to object output stream: 2
  </code></pre>
  
  <p>The application successfully sends the first object but blocks indefinitely on the second. The only difference I can see is that the second write call happens while a read operation is in process on a separate thread. My first instinct was that maybe <code>Socket</code>s don't support simultaneous reading and writing from different threads, but my search of Stack Overflow suggests that they do support this simultaneous operation (full duplex). This is the primary reason I'm confused with the operation of the above code.</p>
  
  <p><b>Client</b></p>
  
  <p>Expected output:</p>
  
  <pre><code>choose (s)erver or (c)lient: c
  reading on object input stream
  read first object on object input stream: 1
  reading second object on object input stream
  read second object on object input stream: 2
  writing confirmation message to object output stream: 42
  confirmation message written to object output stream
  object output stream flushed
  </code></pre>
  
  <p>Actual output:</p>
  
  <pre><code>choose (s)erver or (c)lient: c
  reading first object on object input stream
  read first object on object input stream: 1
  reading second object on object input stream
  </code></pre>
  
  <p>This confirms that the first object was successfully sent and received by the client. The client seems to be waiting on the second object which is never sent by the server due to this strange blocking behavior in the server.</p>
  
  <p>Thanks so much in advance for any advice anyone may be able to give. I'm open to rewriting my code if full duplex is easily achievable in another manner, but If there is a solution using the above structure I would much prefer to stick with that for simplicity of not having to refactor large sections of code.</p>