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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2821658/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:15:58  来源:igfitidea点击:

Java sockets: multiple client threads on same port on same machine?

javasocketsportrelationship

提问by espcorrupt

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:

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

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

回答by Jherico

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

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

回答by G__

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).

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

回答by danben

In this example, your Serveraccepts 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.

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

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 ClientWorkeris thread-safe, as you will have multiple instances executing in parallel.

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

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

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

回答by patros

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.

您可以将服务器 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));  
           }
       }  
   } 

回答by Martijn Courteaux

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.

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

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

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

您可以使用基本 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!");

And for reading use a BufferedReader.

对于阅读,请使用 BufferedReader。

回答by Kashif

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