2014-01-15 3 views
1

Сейчас я немного играю с приложением Client-Server, чтобы общаться через Java-приложение с малиной pi, которая запускает серверное приложение.Java ServerSocket принимает только 2 соединения

Ну, я нашел проблему, и я не нашел возможного решения. Используя следующий код, я могу подключиться дважды к серверу, но после 2 подключений он не будет принимать никаких подключений. Например, я запускаю клиент в первый раз, и он отлично работает. Затем я закрываю клиент и запускаю его снова, и он снова работает. Но если я закрою его и начну в третий раз, он ничего не сделает. Сервер не будет принимать соединение. Я попробовал его с разными компьютерами в своей частной сети, но так и не получил 3-го соединения.

Вот код, который я бегу на сервере:

public class Receiver { 

private final Logger logger = Logger.getLogger(this.getClass().getName()); 

private ServerSocket serverSocket; 
private boolean isRunning; 

public Receiver(int port) { 
    isRunning = true; 
    try { 
     serverSocket = new ServerSocket(port); 
     logger.log(Level.FINER, "start listening at port " + port); 
     logger.log(Level.FINER, "established successful."); 
    } catch (IOException e) { 
     logger.log(Level.SEVERE, "Error while opening socket:\n" + LogUtil.getStackTrace(e)); 
     System.exit(1); 
    } 
} 

/** 
* server starts to listen at the specific port 
*/ 
public void listenServer() { 
    logger.log(Level.FINER, "Server is listening"); 

    while (isRunning) { 
     try { 
      final Socket clientsocket = serverSocket.accept(); 
      logger.log(Level.FINER, "Server accepted Connection from " + clientsocket.getInetAddress()); 
      new Thread(new Runnable() { 

       @Override 
       public void run() { 
        handleConnection(clientsocket); 
       } 
      }).start(); 
     } catch (IOException e) { 
      logger.log(Level.SEVERE, "Connection with Client failed."); 
     } 
    } 
} 

/** 
* handles the given connection 
* 
* @param clientSocket 
*   the given client socket for this connection 
*/ 
private void handleConnection(Socket clientSocket) { 

    ObjectInputStream instream = null; 
    ObjectOutputStream outstream = null; 

    try { 
     outstream = new ObjectOutputStream(clientSocket.getOutputStream()); 
     instream = new ObjectInputStream(clientSocket.getInputStream()); 
     final RequestProcessor processor = new RequestProcessor(); 
     final InetAddress inetAdress = clientSocket.getInetAddress(); 

     logger.log(Level.FINER, "handle connection from " + inetAdress); 

     Object inob; 
     while ((inob = instream.readObject()) != null) { 
      logger.log(Level.FINER, "received Object from " + inetAdress); 
      final ObjectOutputStream finalOutputStream = outstream; 
      final Object finalInob = inob; 

      new Thread() { 
       public void run() { 
        setPriority(MAX_PRIORITY); 
        Object outob; 
        try { 
         outob = processor.processObject(finalInob); 
         logger.log(Level.FINER, "send Respond to: " + inetAdress + " Error: " + (outob instanceof ErrorMessage)); 
         finalOutputStream.writeObject(outob); 
         finalOutputStream.flush(); 
        } catch (IOException e) { 
         logger.log(Level.SEVERE, "Connection closed to " + inetAdress); 
        } 
       } 
      }.start(); 
     } 

     closeConnection(clientSocket, instream, outstream); 
    } catch (IOException e) { 
     logger.log(Level.SEVERE, "Connection closed to " + clientSocket.getInetAddress()); 
    } catch (ClassNotFoundException e) { 
     logger.log(Level.SEVERE, "Connection closed to " + clientSocket.getInetAddress()); 
    } finally { 
     closeConnection(clientSocket, instream, outstream); 
    } 

} 

/** 
* closes InputStream, OutputStream and socket 
* 
* @param socket 
* @param instream 
* @param outstream 
*/ 
private void closeConnection(Socket socket, InputStream instream, OutputStream outstream) { 
    this.isRunning = false; 
    if (instream != null) { 
     try { 
      instream.close(); 
     } catch (IOException e) { 
     } 
    } 
    if (outstream != null) { 
     try { 
      outstream.close(); 
     } catch (IOException e) { 
     } 
    } 
    if (socket != null) { 
     try { 
      socket.close(); 
     } catch (IOException e) { 
     } 
    } 
    logger.log(Level.FINER, "Connection was closed to client " + socket.getInetAddress()); 
} 

/** 
* closes all connections and ends the server 
*/ 
public void endAllConnections() { 
    this.isRunning = false; 

    if (this.serverSocket != null) 
     try { 
      this.serverSocket.close(); 
     } catch (IOException e) { 
      // do nothing 
     } 
     } 
    } 

и вот клиентский код, который я использую для подключения к этому серверу:

public class SocketConnector implements IConnector { 

    private final Logger logger = Logger.getLogger(this.getClass().getName()); 

    private Socket s; 
    private ObjectOutputStream oos; 
    private ObjectInputStream ois; 

    /** 
    * creates a new connection 
    * 
    * @param host 
    *   given host 
    * @param port 
    *   given port 
    * 
    * @throws UnknownHostException 
    * @throws IOException 
    */ 
    public SocketConnector(String host, int port) throws UnknownHostException, IOException { 
     logger.log(Level.FINER, "Establish connection to " + host + ":" + port); 
     s = new Socket(host, port); 
     oos = new ObjectOutputStream(s.getOutputStream()); 
     ois = new ObjectInputStream(s.getInputStream()); 
    } 

     // some methos which use oos and ois. 

ли кто-то, может быть, знаете, почему сервер не принимает никаких подключений, когда 2 клиента подключены и отключены от него? Я googled много arround но не нашел адекватного ответа:/ В журнале сервера говорится, что он даже не принимает новое соединение.

Заранее спасибо :)

+0

Работаете ли вы в Windows? Поскольку я думаю, что существует ограничение на стеки TCP/IP из 2-х соединений на хост, которые вы можете настроить, возившись с реестром Windows (или используя альтернативные имена хостов, такие как IP-адрес и имена хостов) –

+0

Существуют и другие проблемы с этим кодом. 1. Потоки объектов должны быть созданы в методе run(), а не в конструкторе: в противном случае они выполняются в потоке accept(), потенциально блокируя его. 2. ObjectInputStream не возвращает null, если вы не написали нуль, поэтому цикл, пока он не возвращает нуль, не имеет смысла. Он выдает EOFException в конце потока: поймайте его и сломайте, когда вы его получите. @JasonSperske Существует ограничение на отставание TCP, но оно значительно выше 2. – EJP

+0

Спасибо. Ватран решил главную проблему. Я снова посмотрю на это, чтобы следовать вашим советам, чтобы сделать его более чистым EJP :) – chf

ответ

2

ситуация является:
при вызове final Socket clientsocket = serverSocket.accept(); в первый раз, он ждет первого клиента. когда первый клиент подключен, вы передаете этот клиент в поток, затем продолжайте цикл, который вызывает final Socket clientsocket = serverSocket.accept(); второй раз. Поскольку начало потока занимает больше времени, чем переход к следующему циклу, isRunning по-прежнему равен true. В handleConnection(Socket clientSocket) вы звоните в closeConnection(clientSocket, instream, outstream);, которому присваивается isRunning - false. Вот в чем дело. Когда второй клиент подключен, вы также передаете этот клиент другому потоку, затем продолжайте цикл, где isRunning - false, поэтому цикл завершается. Следовательно, вы не можете добраться до третьего клиента.

+0

Спасибо, что была проблема. Позор я этого не видел:/Действительно не видел, что я установил его в false ^^ – chf

Смежные вопросы