多线程套接字通信客户机/服务器

多线程套接字通信客户机/服务器

问题描述:

我写了一个客户端/服务器套接字通讯程序,工作正常。现在我想弄清楚如何使它,使我可以有多个客户端连接到服务器一次。我看过周围,似乎有多种不同的方式来做到这一点。所以我来这里要求你们帮助/建议。

I finished writing a Client/Server Socket communication program that works fine. Now I'm trying to figure out how to make it so that I can have multiple Client connections to the Server at once. I've looked around and there seems to be more than a couple of different ways to do this. so I've come here to ask you guys for help/suggestions.

我的服务器:

public class Server {
    private ServerSocket serverSocket = null;
    private Socket clientSocket = null;

    public Server() {
        try {
            serverSocket = new ServerSocket(7003);
        } catch (IOException e) {
            System.err.println("Could not listen on port: 7003");
            System.exit(1);
        }

        try {
            clientSocket = serverSocket.accept();
        } catch (IOException e) {
            System.err.println("Accept failed");
            System.exit(1);
        }
    }

    public void startServer() throws IOException {
        PrintWriter output = new PrintWriter(clientSocket.getOutputStream(), true);
        BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        String inputLine, outputLine;

        outputLine = "Connected to Server";
        output.println(outputLine);

        while ((inputLine = input.readLine()) != null) {
            // This just determines users input and server ruturns output based on that

            outputLine = this.getServerOutput(inputLine);
            output.println(outputLine);

            if (outputLine.equals("Bye"))
                break;
        }

        output.close();
        input.close();
        clientSocket.close();
        serverSocket.close();
    }
}



我需要让我的构造函数创建线程和 startServer()或者是我的运行方法?

Would I need to make my constructor create threads and startServer() or would be my run method?

ExecutorService 。您的客户端请求处理将是 Runnable run(),每次接受后,您可以调用 ExecutorService.submit(runnableTask)以异步方式服务客户端。


使用ExecutorService的示例。

You should use ExecutorService. Your client request processing would be the run() of a Runnable and after each accept you can call ExecutorService.submit(runnableTask) to asynchronously service the client.

A sample using ExecutorService.

public class MyServer {

    private static MyServer server; 
    private ServerSocket serverSocket;

    /**
     * This executor service has 10 threads. 
     * So it means your server can process max 10 concurrent requests.
     */
    private ExecutorService executorService = Executors.newFixedThreadPool(10);        

    public static void main(String[] args) throws IOException {
        server = new MyServer();
        server.runServer();
    }

    private void runServer() {        
        int serverPort = 8085;
        try {
            System.out.println("Starting Server");
            serverSocket = new ServerSocket(serverPort); 

            while(true) {
                System.out.println("Waiting for request");
                try {
                    Socket s = serverSocket.accept();
                    System.out.println("Processing request");
                    executorService.submit(new ServiceRequest(s));
                } catch(IOException ioe) {
                    System.out.println("Error accepting connection");
                    ioe.printStackTrace();
                }
            }
        }catch(IOException e) {
            System.out.println("Error starting Server on "+serverPort);
            e.printStackTrace();
        }
    }

    //Call the method when you want to stop your server
    private void stopServer() {
        //Stop the executor service.
        executorService.shutdownNow();
        try {
            //Stop accepting requests.
            serverSocket.close();
        } catch (IOException e) {
            System.out.println("Error in server shutdown");
            e.printStackTrace();
        }
        System.exit(0);
    }

    class ServiceRequest implements Runnable {

        private Socket socket;

        public ServiceRequest(Socket connection) {
            this.socket = connection;
        }

        public void run() {

            //Do your logic here. You have the `socket` available to read/write data.

            //Make sure to close
            try {
                socket.close();
            }catch(IOException ioe) {
                System.out.println("Error closing client connection");
            }
        }        
    }
}