20

我是 Java Socket 编程的新手,我试图了解下面的代码是否正确。我的问题是:

我可以在每个线程上有多个客户端尝试连接到同一程序中的服务器实例并期望服务器在客户端之间隔离的情况下读写数据吗?

public class Client extends Thread
{
    ...
    void run()
    {
        Socket socket = new Socket("localhost", 1234);
        doIO(socket);  
    }
}

public class Server extends Thread
{
    ...
    void run()
    {
        // serverSocket on "localhost", 1234
        Socket clientSock = serverSocket.accept();
        executor.execute(new ClientWorker(clientSock));
    }
}

现在我可以在不同线程上有多个客户端实例尝试连接当前机器的同一个端口吗?

例如,

   Server s = new Server("localhost", 1234);
   s.start();
   Client[] c = new Client[10];
   for (int i = 0; i < c.length; ++i)
   {
        c.start();
   }
4

6 回答 6

11

是的,但是只有一个客户端能够按照所写的每个线程执行进行连接。

你可以把你的服务器 run() 放在一个真正的循环中,让多个客户端连接。根据执行者的不同,它们将串行或并行执行。

   public class Server extends Thread  
   {  
       ...  
       void run()  
       {  
           while(true){
              // serverSocket on "localhost", 1234  
              Socket clientSock = serverSocket.accept();  
              executor.execute(new ClientWorker(clientSock));  
           }
       }  
   } 
于 2010-05-12T18:36:57.997 回答
4

只要您只有一个对象尝试绑定端口进行侦听,那么多个客户端连接就没有问题。

于 2010-05-12T18:30:00.600 回答
1

在此示例中,您Server一次接受并处理一个客户端连接。您可以Client尝试连接任意数量的 s,但一次只能处理一个。

由于您没有提供实现,因此您的执行程序逻辑是否是多线程的并不明显。如果执行程序委托给线程池或类似的东西,您需要确保您ClientWorker是线程安全的,因为您将有多个实例并行执行。

我当然假设您Client也是线程安全的,因为您的问题仅与Server.

于 2010-05-12T18:33:33.537 回答
0

是的,您的客户是本地的还是远程的都没有关系。在您的示例中,重要的是 ClientWorker 是线程安全的,因为您的服务器将具有该类的多个实例(每个客户端连接一个实例)。

于 2010-05-12T18:33:05.383 回答
0

所以。开始:

您可以使用一个 serversocket 接受更多客户端,因为您在run-method 中只接受一个。你只需要再打电话accept()

然后,你在你的 for 循环中:首先你必须每次创建一个新Client对象。然后你可以打电话c[i].start();而不是c.start()

现在我可以在不同线程上有多个客户端实例尝试连接当前机器的同一个端口吗?

是的你可以。只需创建新线程并运行它们。这应该可以完美地工作。

期望服务器在客户端之间隔离读写数据

您可以使用您对基本 IO 技术的经验,例如使用 file-io:

OutputStream os = socket.getOutputStream();
PrintStream pw = new PrintStream(os, true); // Or PrintWriter, I don't know what the best one is.
pw.println("Hello, other side of the connection!");

对于阅读,请使用 BufferedReader。

于 2010-05-12T18:37:41.583 回答
0

你可以在这些线上尝试一些东西

public class MultiThreadServer extends Application {
  // Text area for displaying contents
  private TextArea ta = new TextArea();

  // Number a client
  private int clientNo = 0;

  @Override // Override the start method in the Application class
  public void start(Stage primaryStage) {
    // Create a scene and place it in the stage
    Scene scene = new Scene(new ScrollPane(ta), 450, 200);
    primaryStage.setTitle("MultiThreadServer"); // Set the stage title
    primaryStage.setScene(scene); // Place the scene in the stage
    primaryStage.show(); // Display the stage

    new Thread( () -> {
      try {
        // Create a server socket
        ServerSocket serverSocket = new ServerSocket(8000);
        ta.appendText("MultiThreadServer started at " 
          + new Date() + '\n');

        while (true) {
          // Listen for a new connection request
          Socket socket = serverSocket.accept();

          // Increment clientNo
          clientNo++;

          Platform.runLater( () -> {
            // Display the client number
            ta.appendText("Starting thread for client " + clientNo +
              " at " + new Date() + '\n');

            // Find the client's host name, and IP address
            InetAddress inetAddress = socket.getInetAddress();
            ta.appendText("Client " + clientNo + "'s host name is "
              + inetAddress.getHostName() + "\n");
            ta.appendText("Client " + clientNo + "'s IP Address is "
              + inetAddress.getHostAddress() + "\n");
          });

          // Create and start a new thread for the connection
          new Thread(new HandleAClient(socket)).start();
        }
      }
      catch(IOException ex) {
        System.err.println(ex);
      }
    }).start();
  }

  // Define the thread class for handling new connection
  class HandleAClient implements Runnable {
    private Socket socket; // A connected socket

    /** Construct a thread */
    public HandleAClient(Socket socket) {
      this.socket = socket;
    }

    /** Run a thread */
    public void run() {
      try {
        // Create data input and output streams
        DataInputStream inputFromClient = new DataInputStream(
          socket.getInputStream());
        DataOutputStream outputToClient = new DataOutputStream(
          socket.getOutputStream());

        // Continuously serve the client
        while (true) {
          // Receive radius from the client
          double radius = inputFromClient.readDouble();

          // Compute area
          double area = radius * radius * Math.PI;

          // Send area back to the client
          outputToClient.writeDouble(area);

          Platform.runLater(() -> {
            ta.appendText("radius received from client: " +
              radius + '\n');
            ta.appendText("Area found: " + area + '\n');
          });
        }
      }
      catch(IOException e) {
        ex.printStackTrace();
      }
    }
  }

  /**
   * The main method is only needed for the IDE with limited
   * JavaFX support. Not needed for running from the command line.
   */
  public static void main(String[] args) {
    launch(args);
  }
}
于 2017-10-04T12:18:18.743 回答