Сокеты Java: несколько потоков клиентов на одном порту на одном компьютере? - PullRequest
18 голосов
/ 12 мая 2010

Я новичок в Socket-программировании на 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();
   }

Ответы [ 6 ]

10 голосов
/ 12 мая 2010

Да, однако только один клиент сможет подключиться к выполнению потока, как написано.

Вы можете просто поместить сервер 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));  
           }
       }  
   } 
3 голосов
/ 12 мая 2010

Пока у вас есть только один объект, пытающийся связать порт для прослушивания, тогда нет проблем с подключением нескольких клиентов.

1 голос
/ 12 мая 2010

В этом примере ваш Server принимает и обрабатывает по одному клиентскому соединению за раз. Вы можете иметь столько Client с, сколько хотите, чтобы попытаться подключиться, но будет обрабатываться только по одному за раз.

Неясно, является ли ваша логика исполнителя многопоточной, поскольку вы не предоставили реализацию. Если исполнитель делегирует в пул потоков или что-то в этом роде, вам нужно убедиться, что ваш ClientWorker поточно-ориентирован, так как у вас будет несколько экземпляров, выполняющихся параллельно.

Я, конечно, предполагаю, что ваш Client также является поточно-ориентированным, поскольку ваш вопрос касается только Server.

0 голосов
/ 04 октября 2017

Вы можете попробовать что-то на этих линиях

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);
  }
}
0 голосов
/ 12 мая 2010

Итак. Для начала:

Вы можете принять больше клиентов с одним сокетом сервера, потому что вы принимаете только одного в run -методе. Вы просто должны позвонить accept() во второй раз.

Затем вы в цикле for: сначала вы должны каждый раз создавать новый Client объект. Тогда вы можете позвонить c[i].start();, а не c.start().

Теперь я могу иметь несколько клиентов экземпляры в разных темах пытаются подключиться к тому же порту текущая машина?

Да, вы можете. Просто создайте новые темы и запустите их. Это должно работать отлично.

ожидаем, что сервер будет читать и писать данные с изоляцией между клиентами

Вы можете использовать свой опыт базовых методов ввода-вывода, например, 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.

0 голосов
/ 12 мая 2010

Да, не имеет значения, являются ли ваши клиенты локальными или удаленными. В вашем примере важно то, что ClientWorker является поточно-ориентированным, поскольку на вашем сервере будет несколько экземпляров этого класса (по одному на каждое клиентское соединение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...