Java套接字: 一个服务器和多个客户端

6
所以我用Java创建了一个基本的客户端服务器程序。它的起始部分如下所示:
  1. 客户端连接到服务器
  2. 服务器要求客户端输入名称
  3. 客户端回应名称
  4. 服务器向客户端问候
  5. 之后,客户端讲话,服务器会将其重复回来
使用这个教程,我成功实现了这个程序。然而,当我尝试引入多个客户端时出现了问题。我认为多线程应该能够解决,但是第二个客户端一直处于挂起状态,直到第一个客户端退出,它才开始工作(服务器确实接受了第二个客户端的输入,但是没有做任何响应,直到第一个客户端退出)。
以下是我使用的代码:
import java.net.*;
import java.io.*;

public class Server extends Thread {
  private ServerSocket listener;

  public Server(int port) throws IOException {
    listener = new ServerSocket(port);
  }

  public void run() {
    while(true) {
      try {
        Socket server = listener.accept();
        DataOutputStream out = new DataOutputStream(server.getOutputStream());
        out.writeUTF("What is your name?");
        DataInputStream in = new DataInputStream(server.getInputStream());
        String user_name = in.readUTF();
        out.writeUTF("Hello "+user_name);
        while(true) {
          String client_message = in.readUTF();
          out.writeUTF(client_message);
        }
      }
      catch(IOException e) {
        e.printStackTrace();
      }
    }
  }

  public static void main(String[] args) {
    int port = 6006;
    try {
      Thread t = new Server(port);
      t.start();
    } catch(IOException e) {
      e.printStackTrace();
    }
  }
}

能有人解释一下我在做什么错了吗?

我已经查看了使用Runnable而不是Extends Thread的方法,但我在那里遇到了更多问题,所以我想先尝试解决这个问题。


这里没有多线程。 - Cruncher
listener.accept()之后的所有内容都需要在一个扩展线程或实现可运行接口的不同类中。然后,在那一点上启动该线程,您的循环将接受下一个连接。 - Cruncher
2个回答

4

只有线路 listener.accept(); 处理传入的连接。但是,当你连接上客户端之后,你会陷入 while 循环中。你需要创建一个新的 Thread(或者在 ExecutorService 上执行的 Runnable,如果你预计负载很高),并启动它,然后立即接受下一个连接。


@AlexeiKaigorodov 确实很容易误解,现在已经更改了那个词。 - dst

3
简而言之,问题出在以下两点:
1. 你只使用了一个线程作为服务器。 2. 当你调用listener.accept()时会阻塞这个线程。
你需要做以下几件事情:
1. 创建两个类: - Server:和你现在所拥有的类似,但不是实际执行回显服务器的工作,而是生成一个新的线程在一个随机选择的新端口上监听,并向客户端发送该新端口的地址。客户端将接收到新端口号并尝试连接到该端口上的服务器。 - 回显线程:在传递的端口上启动一个新的监听器,并执行回显任务。
或者:
2. 你可以启动一个UDP服务器而不是TCP服务器,那么这些问题就不会存在,但这超出了本问题的范围。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接