2013-03-21 53 views
18

我在我的应用程序中使用ServerSocket时遇到问题。在单独的线程中创建ServerSocket?

我在我的应用程序的构造函数中创建了ServerSocket。套接字的构造函数调用accept()方法来等待客户端连接。

问题是,accept()方法冻结我的整个应用程序,直到客户端连接。所以我想问一下,是否有另一种方法可以在单独的线程中创建整个ServerSocketServerSocket及其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 2013-03-21 07:43:41

+0

查看java.nio.channels.AsynchronousServerSocketChannel并查看它是否符合您的要求。 – Crollster 2013-03-21 07:47:31

+0

还是更好,请看看这个问题:http://stackoverflow.com/questions/8940747/how-should-i-use-asynchronousserversocketchannel-for-accepting-connections – Crollster 2013-03-21 07:49:17

回答

34

通常情况下,我使用N + 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

使用线程池处理客户端,您如何处理接收和发送数据到客户端和从客户端发送数据?我几周前看到的一个解决方案是Hanlder也有2个线程,一个用于发送,另一个用于接收数据。 – Loki 2013-03-21 07:40:04

+0

此外,对于这个主题非常类似但稍微更具描述性的内容,请参阅以下文章:[http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html](http: //tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html) – 2015-05-12 12:37:40

+0

这段代码并不能帮助抵御拒绝服务攻击,其中[accept](http://man7.org/linux/ man-pages/man2/accept.2.html)被攻击者阻止(或限制)。这样的攻击者会阻止你的服务器接受新的客户端。 – 2016-11-17 15:14:40

相关问题