我正在编写Server-Multiclient通信应用程序,我需要创建一个循环并接受客户端的Thread
。我目前的代码是:
Thread acceptor = new Thread() {
public void run() {
while(true){
System.out.println("looking for clients");
try{
Socket s = serverSocket.accept();
clientList.add(new ConnectionToClient(s));
}
catch(IOException e){ e.printStackTrace(); }
}
}
}
};
acceptor.setDaemon(true);
acceptor.start();
但是,当我运行我的应用程序时,文本looking for clients
只出现一次,没有客户端可以连接。
我不明白为什么我的while(true)
循环实际上没有循环,只运行一次。
编辑:
ConnectionToClient
构造函数是:
ConnectionToClient(Socket socket) throws IOException {
this.socket = socket;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Thread read = new Thread(){
public void run(){
while(true){
try {
Object obj = in.readObject();
messages.put(obj);
} catch(IOException | ClassNotFoundException | InterruptedException e) {
e.printStackTrace();
}
}
}
};
read.start();
}
答案 0 :(得分:4)
您正在致电acceptor.setDaemon(true);
。
Its Javadoc解释说:
将此线程标记为守护程序线程 或用户线程。 Java虚拟机仅在退出时退出 运行的线程都是守护线程。
因此,您将唯一正在运行的线程标记为守护程序线程(因为当main
方法结束时您的主线程结束)。你很幸运,你有一个循环的迭代,因为你的VM几乎立即退出,因为没有更多的非守护程序线程。
解决方案:删除标有acceptor.setDaemon(true);
您更新的帖子显示了另一个问题,构造函数ConnectionToClient(Socket socket)
无意中尝试从Socket
读取,这会阻止接受者线程,直到客户端发送数据。
问题是ObjectInputStream
的构造函数尝试读取对象流的标题。
因此,您应该将ObjectInputStream
和ObjectOutputStream
的结构移动到read
主题中,这样就不会阻止acceptor
主题。< / p>
答案 1 :(得分:0)
好的,感谢@ErwinBolwidt。
问题是:
1).setDaemon(true)
导致问题。
2)在连接客户端之前创建ObjectInputStream
是读取需要发送到服务器的标头,并阻止客户端将其发送到服务器。将其移动到读取线程允许客户端实际连接到服务器。
再次感谢@ErwinBolwidt。