2013-03-21 19 views
18

Ho un problema con l'utilizzo di ServerSocket nella mia applicazione.Creazione del ServerSocket in un thread separato?

Sto creando il ServerSocket nel costruttore della mia applicazione. Il costruttore del socket chiama il metodo accept() per attendere la connessione di un client.

Il problema è che il metodo accept() congela la mia intera applicazione fino a quando un client non si connette. Vorrei quindi chiedere se esiste un'alternativa alla creazione dell'intero ServerSocket in un thread separato, che il costruttore del e il suo metodo accept() viene chiamato accanto alla mia applicazione principale?

Edit:

Grazie a Olivier per il consiglio, ponendo l'Accetti in un eseguibile e la creazione di un pool di thread per gestire le clientconnections.

thats il mio codice in questo momento:

public void start(){ 

     final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10); 

     Runnable serverTask = new Runnable() { 
      @Override 
      public void run() { 

       try { 
        serverSocket = new ServerSocket(port); 

        while (true) { 
         Socket clientSocket = serverSocket.accept(); 
         objectout = new ObjectOutputStream(clientSocket.getOutputStream()); 
         clientProcessingPool.submit(new ClientTask(clientSocket,objectout)); 
        } 
       } catch (IOException e) { 
        System.err.println("Accept failed."); 
       } 

      } 
     }; 

Everythings funzionare benissimo! Grazie!

+0

provato a spostare codice relativo socket in thread separato? qualsiasi problema specifico affrontato? – Ankit

+0

Dai un'occhiata a java.nio.channels.AsynchronousServerSocketChannel e verifica se soddisfa i tuoi requisiti. – Crollster

+0

O meglio ancora, dai un'occhiata a questa domanda: http://stackoverflow.com/questions/8940747/how-should-i-use-asynchronousserversocketchannel-for-accepting-connections – Crollster

risposta

34

Di solito, io uso N + 1 thread per questo: uno per ServerSocket, per evitare di bloccare l'intera applicazione in attesa che un client si connetta; e N thread per elaborare le richieste del client, N è la dimensione del pool di thread (è consigliabile utilizzare un pool di thread per creare una nuova discussione per client).

Ecco un esempio (solo codificato, si consiglia di avere una migliore gestione delle eccezioni e così, ma questo è un esempio di lavoro minima)

public class Server { 

    public static void main(String[] args) { 
     new Server().startServer(); 
    } 

    public void startServer() { 
     final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(10); 

     Runnable serverTask = new Runnable() { 
      @Override 
      public void run() { 
       try { 
        ServerSocket serverSocket = new ServerSocket(8000); 
        System.out.println("Waiting for clients to connect..."); 
        while (true) { 
         Socket clientSocket = serverSocket.accept(); 
         clientProcessingPool.submit(new ClientTask(clientSocket)); 
        } 
       } catch (IOException e) { 
        System.err.println("Unable to process client request"); 
        e.printStackTrace(); 
       } 
      } 
     }; 
     Thread serverThread = new Thread(serverTask); 
     serverThread.start(); 

    } 

    private class ClientTask implements Runnable { 
     private final Socket clientSocket; 

     private ClientTask(Socket clientSocket) { 
      this.clientSocket = clientSocket; 
     } 

     @Override 
     public void run() { 
      System.out.println("Got a client !"); 

      // Do whatever required to process the client's request 

      try { 
       clientSocket.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

} 
+0

Con il threadpool che gestisce i client, come gestisci Ricevi e invia dati al e dal client? Una soluzione che ho visto poche settimane fa era che Hanlder ha anche 2 thread, uno per l'invio e uno per ricevere i dati. – Loki

+0

Inoltre, per un argomento molto simile, ma leggermente più descrittivo su questo argomento, vedere il seguente articolo: [http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html](http: //tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html) –

+0

Questo codice non aiuta contro l'attacco denial of service, dove [accept] (http://man7.org/linux/ man-pages/man2/accept.2.html) è bloccato (o limitato) dall'aggressore. Un tale aggressore potrebbe impedire al server di accettare nuovi client. –

Problemi correlati