title: The read from a TCP Server hangs when reading more than once
body: <p>I am testing some TCP code and it seems to work fine except for one problem. The read from the socket hangs in one of the methods when there is nothing more to read:</p>
  
  <p>Here is the TCP code:</p>
  
  <pre><code>package com.comp424.service;
  
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.net.Socket;
  import java.net.UnknownHostException;
  import java.io.IOException;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  
  public class TCPService implements Runnable
  {
      protected int             serverPort;
      protected InetAddress     bindAddress;
  
      protected ServerSocket    serverSocket  = null;
      protected boolean         isStopped     = false;
      protected Thread          runningThread = null;
  
      protected ExecutorService threadPool = Executors.newFixedThreadPool(10);
  
      public TCPService(String host,int port)
      {
          serverPort = port;
  
          try
          {
              bindAddress = InetAddress.getByName(host);
          }
          catch (UnknownHostException e)
          {
              throw new RuntimeException("Failed to get bind address", e);
          }
      }
  
      private void start()
      {
          try
          {
              serverSocket = new ServerSocket(serverPort, 10, bindAddress);
          }
          catch (IOException e)
          {
              throw new RuntimeException("Cannot open port " + serverPort, e);
          }
      }
  
      public void run()
      {
          synchronized (this)
          {
              runningThread = Thread.currentThread();
          }
  
          start();
  
          while (!isStopped())
          {
              Socket clientSocket = null;
  
              try
              {
                  clientSocket = serverSocket.accept();
              }
              catch (IOException e)
              {
                  if (isStopped())
                  {
                      System.out.println("Server Stopped.");
                      break;
                  }
                  throw new RuntimeException("Error accepting client connection", e);
              }
  
              threadPool.execute(new ClientHandler(clientSocket));
          }
          threadPool.shutdown();
  
          System.out.println("Server Stopped.");
      }
  
      public synchronized void stop()
      {
          isStopped = true;
  
          try
          {
              serverSocket.close();
          }
          catch (IOException e)
          {
              throw new RuntimeException("Error closing server", e);
          }
      }    
  
      private synchronized boolean isStopped()
      {
          return isStopped;
      }  
  }
  
  package com.comp424.service;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  import java.net.Socket;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.StringTokenizer;
  
  import com.comp424.impl.dao.DaoFactory;
  import com.comp424.intf.dao.ICourseDao;
  import com.comp424.intf.dao.IPersonDao;
  import com.comp424.intf.dao.IRegisterCourseDao;
  import com.comp424.model.Course;
  import com.comp424.model.Person;
  
  public class ClientHandler implements Runnable
  {
      private static IRegisterCourseDao registrationDao;
      private static IPersonDao         personDao;
      private static ICourseDao         courseDao;
  
      protected Socket                  clientSocket = null;
  
      public ClientHandler(Socket socket)
      {
          registrationDao = DaoFactory.getInstance().getCourseRegistrationDao();
          personDao = DaoFactory.getInstance().getPersonDao();
          courseDao = DaoFactory.getInstance().getCourseDao();
          clientSocket = socket;
      }
  
      public void run()
      {
          try
          {
              String command = null;
  
              OutputStream output = clientSocket.getOutputStream();
              BufferedReader buffer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
  
              command = buffer.readLine();
  
              while (command != null)
              {
                  String separator = ":";
  
                  StringTokenizer tokenizer = new StringTokenizer(command, separator);
  
                  List&lt;String&gt; tokens = new ArrayList&lt;&gt;();
  
                  while (tokenizer.hasMoreElements())
                  {
                      tokens.add((String) tokenizer.nextElement());
                  }
  
                  int operation = Integer.parseInt(tokens.get(0));
  
                  switch (operation)
                  {
                      case 1:
                          try
                          {
                              Person person = personDao.findByID(Long.parseLong(tokens.get(1)));
                              Course course = courseDao.findByID(Long.parseLong(tokens.get(2)));
  
                              registrationDao.register(person, course);
                              output.write(("0\r\n").getBytes());
                          }
                          catch (Exception e)
                          {
                              e.printStackTrace();
                              output.write(("1\r\n").getBytes());
                          }
                          break;
  
                      case 2:
                          try
                          {
                              Person person = personDao.findByID(Long.parseLong(tokens.get(1)));
                              Course course = courseDao.findByID(Long.parseLong(tokens.get(2)));
  
                              registrationDao.register(person, course);
                              output.write(("0\r\n").getBytes());
                          }
                          catch (Exception e)
                          {
                              e.printStackTrace();
                              output.write(("1\r\n").getBytes());
                          }
                          break;
  
                      case 3:
                          try
                          {
                              Person person = personDao.findByID(Long.parseLong(tokens.get(1)));
  
                              List&lt;Course&gt; courses = registrationDao.findByPerson(person);
  
                              for (Course c : courses)
                              {
                                  output.write((c.getName() + "\r\n").getBytes());
                              }
                          }
                          catch (Exception e)
                          {
                              e.printStackTrace();
                              output.write(("1\r\n").getBytes());
                          }
                          break;
  
                  }
                  command = buffer.readLine();
              }
  
              output.close();
          }
          catch (IOException e)
          {
              // report exception somewhere.
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>And here is the code where it just hangs in findRegisteredCourses() after reading two strings returned instead of exiting the while loop:</p>
  
  <pre><code>    while (response != null)
      {
          result.add(response);
          System.out.println("findRegisteredCourses():Response = " + response);
          response = reader.readLine();
  
      }
  </code></pre>
  
  <p>Full code for findRegisteredCourses():</p>
  
  <pre><code>    @Override
      public List&lt;String&gt; findRegisteredCourses(String personID) throws Exception
      {
          try (Socket server = new Socket("localhost", 7000))
          {
              List&lt;String&gt; result = new ArrayList&lt;&gt;();
  
              DataOutputStream writer = new DataOutputStream(server.getOutputStream());
              BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream()));
  
              String operation = "3:" + personID + "\r\n";
              writer.writeBytes(operation);
              writer.flush();
  
              String response = reader.readLine();
  
              while (response != null)
              {
                  result.add(response);
                  System.out.println("findRegisteredCourses():Response = " + response);
                  response = reader.readLine();
  
              }
              server.close();
              return result;
          }
      }
  </code></pre>