2013-03-21 13 views
18

Ich habe ein Problem mit der Verwendung einer ServerSocket in meiner Anwendung.ServerSocket in einem separaten Thread erstellen?

Ich erstelle die ServerSocket im Konstruktor meiner Anwendung. Der Konstruktor des Sockets ruft die Methode accept() auf, um darauf zu warten, dass ein Client eine Verbindung herstellt.

Das Problem ist, dass die accept() Methode meine gesamte Anwendung einfriert, bis ein Client verbindet. Also würde ich gerne fragen, ob es eine Alternative zum Erstellen der gesamten ServerSocket in einem separaten Thread gibt, dass der Konstruktor der ServerSocket und seine accept() Methode neben meiner Hauptanwendung aufgerufen wird?

Edit:

Dank Olivier für die Beratung, die .Accept in ein lauffähiges setzen und die Schaffung eines Thread die clientconnections zu behandeln.

Das ist jetzt mein Code:

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."); 
       } 

      } 
     }; 

Every läuft gut! Vielen Dank!

+0

versucht Buchse bezogenen Code in separaten Thread zu verschieben? irgendein spezifisches Problem konfrontiert? – Ankit

+0

Werfen Sie einen Blick auf java.nio.channels.AsynchronousServerSocketChannel und sehen Sie, ob es Ihren Anforderungen entspricht. – Crollster

+0

Oder noch besser, werfen Sie einen Blick auf diese Frage: http://StackOverflow.com/Questions/8940747/how-should-i-use-asynchronousserversocketchannel-for-accepting-connections – Crollster

Antwort

34

Normalerweise verwende ich N + 1 Threads für dieses: eins für den ServerSocket, um zu vermeiden, die gesamte Anwendung zu blockieren, die darauf wartet, dass ein Client eine Verbindung herstellt; und N Threads, um die Anforderungen des Clients zu verarbeiten, wobei N die Größe des Thread-Pools ist (ich empfehle, einen Thread-Pool zu verwenden, um einen neuen Thread pro Client zu erstellen). Hier

ist ein Beispiel (es gerade codiert, möchten Sie vielleicht eine bessere Verwaltung von Ausnahmen und so haben, aber dies ist ein minimales Arbeitsbeispiel)

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

Wie gehen Sie mit dem Threadpool, der die Clients behandelt, um, Daten vom und zum Client zu empfangen und zu senden? Eine Lösung, die ich vor einigen Wochen gesehen habe, war, dass der Hanlder auch zwei Threads hat, einen zum Senden und einen zum Empfangen von Daten. – Loki

+0

Siehe auch den folgenden Artikel für eine sehr ähnliche, aber etwas anschaulichere Darstellung zu diesem Thema: [http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html](http: //tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html) –

+0

Dieser Code hilft nicht gegen den Denial-of-Service-Angriff, wo [akzeptieren] (http://man7.org/linux/ man-pages/man2/accept.2.html) wird vom Angreifer blockiert (oder gedrosselt). Ein solcher Angreifer würde Ihren Server davon abhalten, neue Clients zu akzeptieren. –

Verwandte Themen