title: Java socket: Connection reset
body: <p>I have browsed, searched ... and nothing sparkles to my mind!</p>
  
  <p>I am running a chat type service between a server and an Android app. The client connects, the server registers the socket, and every 10 minutes the server sends to all connected devices a message.</p>
  
  <p>My problem is that randomly I have a connection reset exception. I can not trace back when the problem occurs.</p>
  
  <p><strong>My server side code is:</strong></p>
  
  <pre><code>final public class ChatRoomService {
      private final static String AUTHENTICATE = "AUTHENTICATE";
      private final static String BROADCAST = "BROADCAST";
      private final static String DISCONNECT = "DISCONNECT";
      private final static String OK = "OK";
      private final static String NOK = "NK";
  
      private final static Logger LOGGER = Logger.getLogger(ChatRoomService.class);
  
      private ServerSocket listener = null;
  
      @Inject
      private EntityManager entityManager;
      public EntityManager getEntityManager() {
          return entityManager;
      }
  
      @Inject
      private PlayerManager playerManager;
      PlayerManager getPlayerManager() {
          return playerManager;
      }
  
      private static HashSet&lt;ChatRoomConnection&gt; connections = new HashSet&lt;ChatRoomConnection&gt;();
      public void addConnection(ChatRoomConnection c) {
          synchronized(connections) {
              connections.add(c);
          }
      }
      public void removeConnection(ChatRoomConnection c) {
          synchronized(connections) {
              connections.remove(c);
          }
      }
  
      public void startListeningToChatRoomConnection() throws IOException {
          listener = new ServerSocket(9010);
  
          try {
              LOGGER.infof("startListening - Start listening on port %s", 9010);
              while (true) {
                  ChatRoomConnection connection = new ChatRoomConnection(listener.accept(), this);
                  addConnection(connection);
                  connection.start();
              }
          } catch (IOException e) {
              if (!listener.isClosed())
                  LOGGER.errorf("listenToChatRoomConnection - Connection lost during connection: %s", e.getMessage());
          } finally {
              if (listener != null &amp;&amp; !listener.isClosed()) {
                  LOGGER.infof("listenToChatRoomConnection - Stop listening");
                  listener.close();
              }
          }
      }
  
      public void stopListeningToChatRoomConnection() throws IOException {
          if (!listener.isClosed()) {
              LOGGER.infof("stopListeningToChatRoomConnection - Stop listening");
  
              listener.close();
              listener = null;
  
              // Closing all sockets
              for (ChatRoomConnection connection : connections) {
                      connection.close();
              }
              // Clear up the connections list
              synchronized (connections) {
                  connections.clear();
              }
          }
      }
  
      public void broadcastToChatRoomClients(Object message) {
          synchronized (connections) {
              // Log
              LOGGER.debugf("Broadcast ChatRoom: %s - %s", 
                      connections.size(),
                      message.toString());
  
              for (ChatRoomConnection connection : connections) {
                  LOGGER.debugf("Broadcast ChatRoom to %s", connection.userName);
                  connection.publish(message);
              }
          }
      }
  
      private ChatRoomService() {
      }
  
      private static class ChatRoomConnection extends Thread {
          private Socket socket;
          private BufferedReader readerFromClient;
          private PrintWriter writerToClient;
          public String userName;
  
          private ChatRoomService chatCService;
  
          ChatRoomConnection(Socket socket, ChatRoomService chatRoomService) {
              super("ChatRoomConnection");
  
              this.socket = socket;
              this.chatRoomService = chatRoomService;
          }
  
          public void run() {
              try {
                  readerFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                  writerToClient = new PrintWriter(socket.getOutputStream(), true);
  
                  // 1- Authenticate the Device/ Player
                  writerToClient.println(ChatRoomService.AUTHENTICATE);   
                  writerToClient.flush();
                  Gson gson = new Gson();
                  Request request = gson.fromJson(readerFromClient.readLine(), Request.class);
                  if (chatRoomService.getPlayerManager().isPlayerSignedIn(request.getPlayerId(), request.getSignedInOn())) {
                      Player player = (Player) chatRoomService.getEntityManager().find(Player.class, request.getPlayerId());
                      userName = player.getUsername();
                      LOGGER.infof("listenToChatRoomConnection - Connection established with %s", userName);
                      writerToClient.println(ChatRoomService.OK); 
                      writerToClient.flush();
                      while (true)
                          if ((readerFromClient.readLine() == null) || 
                              (readerFromClient.readLine().startsWith(ChatRoomService.DISCONNECT)))
                          break;
                  } else {
                      writerToClient.println(ChatRoomService.NOK);
                      writerToClient.flush();
                  }
              } catch (Exception e) {
                  LOGGER.errorf("listenToChatRoomConnection - Error with %s: %s", userName, e.getMessage());
                  e.printStackTrace();
              } finally {
                  try {
                      if (!socket.isClosed()) {
                          LOGGER.infof("listenToChatRoomConnection - Connection closed by the client for %s", userName);
                          socket.close();
                      }
                  } catch (IOException e) {
                      LOGGER.errorf("listenToChatRoomConnection - Can not close socket: %s", e.getMessage());
                      e.printStackTrace();
                  } finally {
                      chatRoomService.removeConnection(this);
                  }
              }
          }
  
          public void publish(Object message) {
              if (!socket.isClosed()) {
                  writerToClient.println(ChatRoomService.BROADCAST);
                  Gson gson = new Gson();
                  writerToClient.println(gson.toJson(message));
              }
          }
  
          public void close() {
              writerToClient.println(ChatRoomService.DISCONNECT);
              try {
                  LOGGER.infof("listenToChatRoomConnection - Connection closed by the server for %s", userName);
                  socket.close();
              } catch (IOException e) {
                  LOGGER.errorf("Error when trying to close a socket: %s", e.getMessage());
                  e.printStackTrace();
              }
          }
      };
  }
  </code></pre>
  
  <p><strong>The device code is:</strong></p>
  
  <pre><code>public class ServerBroadcastManager {
      private static final String TAG = ServerBroadcastManager.class.getName();
  
      // Type of messages from the server
      static public String AUTHENTICATE = "AUTHENTICATE";
      static public String DISCONNECT = "DISCONNECT";
      static public String BROADCAST = "BROADCAST";
      static public String OK = "OK";
      static public String NOK = "NK";
  
      private int networkPort;
      private ServerBroadcastListener broadcastListener;
      private Socket networkSocket;
  
      BufferedReader in;
      PrintWriter out;
  
      public ServerBroadcastManager(Context context, ServerBroadcastListener listener, int port) {
      this.networkPort = port;
      this.broadcastListener = listener;
      }
  
      public void startListening(final Context context) {
      Runnable run = new Runnable() {
          @Override
          public void run() {
              // Make connection and initialize streams
              try {
                  networkSocket = new Socket();
                  networkSocket.connect(new InetSocketAddress(mydomain, networkPort), 30*1000);
                  in = new BufferedReader(new InputStreamReader(
                          networkSocket.getInputStream()));
                  out = new PrintWriter(networkSocket.getOutputStream(), true);
  
                  // Process all messages from server, according to the protocol.
                  while (true) {
                      String line = in.readLine();
                      if (line.startsWith(ServerBroadcastManager.AUTHENTICATE)) {
                          Request request = formatAuthenticateRequest(context);
                          Gson requestGson = new Gson();          
                          out.println(requestGson.toJson(request));
                          out.flush();
                          // Waiting for confirmation back
                          line = in.readLine();
                          if (line.startsWith(ServerBroadcastManager.OK)) {
                          } else if (line.startsWith(ServerBroadcastManager.NOK)) {
                          }
                      } else if (line.startsWith(ServerBroadcastManager.BROADCAST)) {
                          Gson gson = new Gson();
                          @SuppressWarnings("unchecked")
                          LinkedHashMap&lt;String,String&gt; broadcast = gson.fromJson(in.readLine(), LinkedHashMap.class);
                          broadcastListener.processBroadcast(broadcast);
                      } else if (line.startsWith(ServerBroadcastManager.DISCONNECT)) {
                          break;
                      }
                  }
              } catch (UnknownHostException e) {
                      Log.i(TAG, "Can not resolve hostname");
              } catch (SocketTimeoutException e) {
                      Log.i(TAG, "Connection Timed-out");
  
                  broadcastListener.connectionFailed();
              } catch (IOException e) {
                      Log.i(TAG, "Connection raised on exception: " + e.getMessage());
  
                  if (!networkSocket.isClosed()) {
                      broadcastListener.connectionLost();
                  }
              }
          }           
      };
  
      Thread thread = new Thread(run);
      thread.start();
  }
  
  public void stopListening() {
      try {
          if (networkSocket != null)
              networkSocket.close();
      } catch (IOException e) {
              Log.i(TAG, "Exception in stopListening: " + e.getMessage());
      }
  }
  
  private Request formatAuthenticateRequest(Context context) {
      Request request = new Request();
      SharedPreferences settings = context.getApplicationContext().getSharedPreferences(Constants.USER_DETAILS, 0);
  
      request.setPlayerId(BigInteger.valueOf((settings.getLong(Constants.USER_DETAILS_PLAYERID, 0))));
      request.setSignedInOn(settings.getLong(Constants.USER_DETAILS_SIGNEDINON, 0));
  
      return request;
      }
  }
  </code></pre>
  
  <p>My last resort might be to move my server to another location, and see if this could not be related to my broadband router. I have notice that some of my HTTP call do not reach the server as well, though port forwarding is properly in place.</p>
  
  <p>Thanks.
  David.</p>