Java 客户机-服务器程序的多线程处理

Java 客户机-服务器程序的多线程处理,java,multithreading,sockets,client-server,Java,Multithreading,Sockets,Client Server,我正在尝试用我一直在开发的客户机/服务器程序实现多线程。我需要允许多个客户端同时连接到服务器。我目前有4个类:一个客户端、一个服务器、一个协议和一个工作线程。以下代码是这些类的代码: SocketServer类: public class SocketServer { public static void main(String[] args) throws IOException { int portNumber = 9987; try (

我正在尝试用我一直在开发的客户机/服务器程序实现多线程。我需要允许多个客户端同时连接到服务器。我目前有4个类:一个客户端、一个服务器、一个协议和一个工作线程。以下代码是这些类的代码:

SocketServer类:

public class SocketServer {


     public static void main(String[] args) throws IOException {

        int portNumber = 9987;

        try ( 
            ServerSocket serverSocket = new ServerSocket(portNumber);
            Socket clientSocket = serverSocket.accept();
            PrintWriter out =
                new PrintWriter(clientSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));

        ) {
            Thread thread = new Thread(new ClientWorker(clientSocket));
            thread.start(); //start thread

            String inputLine, outputLine;

            // Initiate conversation with client
            Protocol prot = new Protocol();
            outputLine = prot.processInput(null);
            out.println(outputLine);

            while ((inputLine = in.readLine()) != null) {
                outputLine = prot.processInput(inputLine);
                out.println(outputLine);
                if (outputLine.equals("quit"))
                    break;
            }
        } catch (IOException e) {
            System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
            System.out.println(e.getMessage());
        }
    }
}
SocketClient类:

public class SocketClient {
     public static void main(String[] args) throws IOException 
    {

        String hostName = "localhost";
        int portNumber = 9987;

        try (
            Socket socket = new Socket(hostName, portNumber);
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
        ) {
            BufferedReader stdIn =
            new BufferedReader(new InputStreamReader(System.in));
            String fromServer;
            String fromUser;

            while ((fromServer = in.readLine()) != null) {
                System.out.println("Server: " + fromServer);
                if (fromServer.equals("quit"))
                    break;

                fromUser = stdIn.readLine();
                if (fromUser != null) {
                    System.out.println("Client: " + fromUser);
                    out.println(fromUser);
                }
            }
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host " + hostName);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to " +
                hostName);
            System.exit(1);
        }
    }
}
协议类别:

public class Protocol {

    private static final int waiting         = 0;
    private static final int sentPrompt      = 1;


    private int status = waiting;

     public String processInput(String theInput) {
         String theOutput = null;

        if (status == waiting) {
            theOutput = "Please enter what you would like to retrieve: 'customer' or 'product' ";
            status = sentPrompt;
        }
        else if ( status == sentPrompt ) {
            if ( theInput.equalsIgnoreCase("product")) {
                File f = new File("product.txt");
                Scanner sc = null;
                try {
                    sc = new Scanner(f);
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(Protocol.class.getName()).log(Level.SEVERE, null, ex);
                }

                while ( sc.hasNextLine()  ) {
                    String line   = sc.nextLine();
                    theOutput = "The current product entries are : " + line;
                }
                return theOutput;
            }
            else if ( theInput.equalsIgnoreCase("customer")) {
                File f = new File("customer.txt");
                Scanner sc = null;
                try {
                    sc = new Scanner(f);
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(Protocol.class.getName()).log(Level.SEVERE, null, ex);
                }

                while ( sc.hasNextLine()  ) {
                    String line   = sc.nextLine();
                    theOutput = "The current customer entries are : " + line;
                }
                return theOutput;

            }
            else if ( theInput.equalsIgnoreCase("quit")) {
                return "quit";
            }
            else {
                return "quit";
            }
        }
        return theOutput;
    }
}
ClientWorker类:

public class ClientWorker implements Runnable {
    private final Socket client;

    public ClientWorker( Socket client ) {
        this.client = client;
    }

    @Override
    public void run() {
        String line;
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            System.out.println("Thread started with name:"+Thread.currentThread().getName());
            in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            out = new PrintWriter(client.getOutputStream(), true);
        } catch (IOException e) {
            System.out.println("in or out failed");
            System.exit(-1);
        }

        while (true) {
            try {
                System.out.println("Thread running with name:"+Thread.currentThread().getName());
                line = in.readLine();
                //Send data back to client
                out.println(line);
                //Append data to text area
            } catch (IOException e) {
                System.out.println("Read failed");
                System.exit(-1);
            }
        }
    }       
}

当我运行服务器和客户端时,一切正常。然后,当我尝试运行另一个客户机时,它只是挂在那里,不会提示客户机给出响应。非常感谢您对我所缺少的任何见解

调用了多少次
serverSocket.accept()
? 一旦 这就是它将处理的客户数量。 试图联系的后续客户将不会有任何人接听


要处理更多客户端,您需要在循环中调用
serverSocket.accept()

调用
serverSocket.accept()
多少次? 一旦 这就是它将处理的客户数量。 试图联系的后续客户将不会有任何人接听


要处理更多客户端,您需要在循环中调用
serverSocket.accept()

您的服务器代码应该实现以下功能

  • 保持在while循环中接受来自的套接字

  • 通过传递客户端套接字,即

  • 在客户端套接字线程中执行IO处理,例如在您的情况下执行
    ClientWorker

  • 看看这个

    你的代码应该是

    ServerSocket serverSocket = new ServerSocket(portNumber);
    while(true){
      try{
        Socket clientSocket = serverSocket.accept();
        Thread thread = new ClientWorker(clientSocket);
        thread.start(); //start thread
      }catch(Exception err){
         err.printStackTrace();
      }
    }
    

    您的服务器代码应该解决实现以下功能的问题

  • 保持在while循环中接受来自的套接字

  • 通过传递客户端套接字,即

  • 在客户端套接字线程中执行IO处理,例如在您的情况下执行
    ClientWorker

  • 看看这个

    你的代码应该是

    ServerSocket serverSocket = new ServerSocket(portNumber);
    while(true){
      try{
        Socket clientSocket = serverSocket.accept();
        Thread thread = new ClientWorker(clientSocket);
        thread.start(); //start thread
      }catch(Exception err){
         err.printStackTrace();
      }
    }
    

    你的程序具体挂在哪里?我猜在ServerSocket的while循环中。@hotzst:是的。我对使用其他方法持开放态度,我也一直在研究线程池。但是我需要在每一个线程中使用这个协议。代码质量的旁注:这个代码几乎是可怕的“不干净”。例如,我衷心建议从Robert Martin开始编写“干净的代码”,以了解您可以通过多少方式改进源代码。@Jägermeister:注意。好的,谢谢。你的程序具体挂在哪里?我猜在ServerSocket的while循环中。@hotzst:是的。我对使用其他方法持开放态度,我也一直在研究线程池。但是我需要在每一个线程中使用这个协议。代码质量的旁注:这个代码几乎是可怕的“不干净”。例如,我衷心建议从Robert Martin开始编写“干净的代码”,以了解您可以通过多少方式改进源代码。@Jägermeister:注意。好的,谢谢。谢谢!我是保留协议proceInput的try/catch还是将其移动到ClientWorker run()方法?try{}catch{}中的ClientWorker应该很好谢谢!我是保留协议proceInput的try/catch还是将其移动到ClientWorker run()方法?try{}catch{}中的ClientWorker应该可以