Java套接字:同一台机器上同一端口上的多个客户端线程?

发布于 2024-09-01 16:04:18 字数 763 浏览 7 评论 0原文

我是 Java 套接字编程的新手,并试图了解下面的代码是否是错误的做法。我的问题是:

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

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();
   }

I am new to Socket programming in Java and was trying to understand if the below code is not a wrong thing to do. My question is:

Can I have multiple clients on each thread trying to connect to a server instance in the same program and expect the server to read and write data with isolation between clients"

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

Now can I have multiple Client instances on different threads trying to connect on the same port of the current machine?

For example,

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

过气美图社 2024-09-08 16:04:18

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

您可以将服务器 run() 放入 while true 循环中,以让多个客户端连接。
根据执行者的不同,它们将串行或并行执行。

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

Yes, however only one client will be able to connect per thread execution as written.

You can just put your server run() inside a while true loop to let multiple clients connect.
Depending on the executor, they will execute either in series or parallel.

   public class Server extends Thread  
   {  
       ...  
       void run()  
       {  
           while(true){
              // serverSocket on "localhost", 1234  
              Socket clientSock = serverSocket.accept();  
              executor.execute(new ClientWorker(clientSock));  
           }
       }  
   } 
饮惑 2024-09-08 16:04:18

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

As long as you only have one object trying to bind the port for listening, then there's no problem with multiple clients connecting.

羁客 2024-09-08 16:04:18

在此示例中,您的服务器一次接受并处理一个客户端连接。您可以尝试连接任意多个客户端,但一次只会处理一个。

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

我当然假设您的客户端也是线程安全的,因为您的问题仅涉及服务器。

In this example, your Server accepts and handles one client connection at a time. You can have as many Clients as you want attempting to connect, but only one at a time will be handled.

It is not apparent whether your executor logic is multithreaded, since you didn't provide the implementation. If the executor delegates to a threadpool or something like that, you would need to make sure that your ClientWorker is thread-safe, as you will have multiple instances executing in parallel.

I am of course assuming that your Client is thread-safe as well, since your question is only concerning the Server.

如日中天 2024-09-08 16:04:18

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

Yes, it doesn't matter whether your clients are local or remote. The important thing in your example is that ClientWorker is thread-safe, as your server will have multiple instances of that class (one for each client connection).

窗影残 2024-09-08 16:04:18

所以。首先:

您可以使用一个服务器套接字接受更多客户端,因为您在 run 方法中只接受一个客户端。您只需再次调用 accept() 即可。

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

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

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

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

您可以利用基本 IO 技术的经验,例如文件 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 进行读取。

So. To begin:

You can accept more clients with one serversocket, because you accept only one in the run-method. You have just to call accept() a second time.

Then, you in your for loop: first you have to create each time a new Client object. Then you can call c[i].start(); and not c.start().

Now can I have multiple Client
instances on different threads trying
to connect on the same port of the
current machine?

Yes you can. Just create new Threads and run them. This should work perfectly.

expect the server to read and write
data with isolation between clients

You can use your experience of the basic IO techniques like with 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!");

And for reading use a BufferedReader.

要走干脆点 2024-09-08 16:04:18

你可以尝试一下这些行

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

You can try something on these lines

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);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文