嘿堆栈溢出。
所以我一直在做一个聊天程序来教自己一些Java,我把它运行到任意数量的客户端可以自由连接到服务器的程度,但每个客户端只能与服务器通信。
这显然是一个糟糕的聊天程序,所以我实现了一个处理程序的arrayList,目的是发送一个客户端写入所有客户端的内容。问题是我无法正常工作,现在我的程序在客户端和服务器之间输入3行文本后崩溃。
请查看我的代码。我将重点介绍在尝试实现数组列表时我更改的代码部分。我想我只是把事情搞错了。
服务器代码:
import java.io.*;
import java.net.*;
import java.util.*;;
public class Server{
//----------------------------------------------------
ArrayList<Handler> handlers = new ArrayList<Handler>();
//----------------------------------------------------
public static void main(String[] args){
try{
ServerSocket ss = new ServerSocket(8822);
while(true){
Socket s = ss.accept();
new Handler(s).start();
}
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
class Handler extends Thread{
Socket socket;
boolean notdone;
BufferedReader br;
PrintWriter pw;
String line;
public Handler(Socket socket){
this.socket = socket;
notdone = true;
}
public void run(){
//------------------
handlers.add(this);
//------------------
try{
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
//--------------------------------------------------------
Iterator<Handler> handlerIterator = handlers.iterator();
//--------------------------------------------------------
while(notdone){
line = br.readLine();
if(line.equals("bye")){
System.out.println("Client said 'bye'");
notdone = false;
break;
}else{
System.out.println("Echo: " + line);
//----------------------------------------------
while (handlerIterator.hasNext()){
Handler current = handlerIterator.next();
current.pw.println(line);
}
//----------------------------------------------
}
}
br.close();
pw.close();
socket.close();
}catch(Exception e){
System.out.println(e);
System.out.println("Client severed connection.");
}
}
}
至于客户,我想我应该在突出显示的部分更改一些内容, 但我不确定是什么。
客户代码:
import java.io.*;
import java.net.*;
import java.util.*;
public class Client{
public static void main(String[] args){
try{
Socket s = new Socket("localhost", 8822);
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()),true);
Scanner scan = new Scanner(System.in);
boolean notdone = true;
while(notdone){
String outString = scan.nextLine();
if(outString.equals("bye")){
pw.println(outString);
notdone = false;
}else{
//------------------
pw.println(outString);
String inString = br.readLine();
//------------------
System.out.println("Received: " + inString);
}
}
br.close();
pw.close();
s.close();
}catch(Exception e){
System.out.println("Server severed connection.");
}
}
}
答案 0 :(得分:2)
这是你的一个错误:
Iterator<Handler> handlerIterator = handlers.iterator();
while(notdone){
// ...
while (handlerIterator.hasNext()){
Handler current = handlerIterator.next();
// ....
}
}
第一次通过外循环时,您将通过内循环。通过外部循环的{em>秒时间handlerIterator
已经用尽,因此它将为false
返回hasNext()
,您将永远不再进入内循环
相反,使用for-each循环:
while(notdone){
// ...
for (Handler current : handlers){
// ....
}
}
这相当于(但更简洁)
while(notdone){
// ...
Iterator<Handler> handlerIterator = handlers.iterator()
while (handlerIterator.hasNext()){
Handler current = handlerIterator.next();
// ....
}
}
同时,在客户端,
pw.println(outString);
String inString = br.readLine();
表示您只从服务器读取并且始终在写入服务器之后。所以客户不能只听。这对单个客户端来说应该没问题,但是如果你有两个客户端,那么你会得到这个:
所以现在两个客户都看到了ClientA的消息,但没有看到ClientB的消息。你将继续获得这种奇怪的延迟效果,最终缓冲区将被填满并阻塞。
真正的解决方案是每个客户端都需要一个单独的线程来进行读写。但这在代码难度上是一个相当大的跳跃。我想你应该看看BufferedReader#ready(),它告诉你是否有数据等待阅读。在客户端,您可以在while-not-done循环的开头使用它:
while(br.ready()) {
String inString = br.readLine();
// ...
}
// Now all the messages from the server have been printed
你仍然会遇到客户需要不断交谈的问题,但只要他们这样做,事情就应该有效。