2013-03-21 9 views
18

私のアプリケーションでServerSocketを使用する際に問題があります。別のスレッドでServerSocketを作成しますか?

私はアプリケーションのコンストラクタにServerSocketを作成しています。ソケットのコンストラクタは、クライアントが接続するのを待つためにaccept()メソッドを呼び出します。

問題は、クライアントが接続するまで、accept()メソッドがアプリケーション全体をフリーズしていることです。だから別のスレッドでServerSocket全体を作成する代わりに、ServerSocketのコンストラクタとそのaccept()メソッドがメインアプリケーションの横に呼び出されているかどうかを尋ねたいと思いますか?

編集:アドバイスオリヴィエへ

おかげで、実行可能に.acceptを入れてclientconnectionsを処理するスレッドプールを作成します。今私のコードザッツ

:罰金を実行している

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

      } 
     }; 

何もかも!ありがとう!

+0

のですか?特定の問題に直面していますか? – Ankit

+0

java.nio.channels.AsynchronousServerSocketChannelを見て、それがあなたの必要条件を満たすかどうかを確認してください。 – Crollster

+0

または、より良いまだ、この質問を見て:http://stackoverflow.com/questions/8940747/how-should-i-use-asynchronousserversocketchannel-for-accepting-connections – Crollster

答えて

34

通常、このためにN + 1スレッドを使用します.1つはServerSocket用で、クライアントが接続するのを待っているアプリケーション全体をブロックしないようにします。クライアントの要求を処理するためのN個のスレッド(スレッドプールのサイズはNです)(クライアントごとに新しいスレッドを作成するよりもスレッドプールを使用することをお勧めします)。別のスレッドでソケットに関連するコードを移動しようとした。ここ

は例(ちょうどそれをコード化され、あなたがより良い例外管理などを持っている場合がありますが、これは、最小限の作業例です)

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

スレッドプールでクライアントを処理すると、クライアントとの間で送受信データをどのように処理しますか?私が数週間前に見た1つの解決策は、Hanlderには送信用とデータ受信用の2つのスレッドがあることでした。 – Loki

+0

また、非常によく似ていますが、このトピックについてもう少し詳しく説明するには、次の記事を参照してください。[http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html]http: //tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html) –

+0

このコードは、[accept](http://man7.org/linux/)というサービス拒否攻撃に対しては役立ちません。 man-pages/man2/accept.2.html)は、攻撃者によってブロックされます(または抑制されます)。そのような攻撃者は、サーバーが新しいクライアントを受け入れるのを止めます。 –

関連する問題