我已经尝试过使该程序每次都进行三遍,以使程序更进一步。我的程序应该像这样工作:
客户端将消息发送到服务器,然后服务器将消息发送到所有连接的客户端(包括发送消息的客户端)。客户端收到消息后,便显示该消息。
我现在面临的问题是服务器仅将消息发送给发送该消息的客户端,而其他客户端什么也没收到。我认为这种情况的发生是因为我接受客户的方式,或者至少某种程度上与此相关。
这是我当前的代码:
客户:
public class Client {
protected static JTextArea textArea = new JTextArea(20, 30);
protected static String sendMSG, getMSG;
public static void main(String[] args) throws IOException {
String hostName = args[0];
String Username = args[1];
boolean sending = true;
try (
Socket socket = new Socket(hostName, 1011);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
//frame setup
JFrame frame = new JFrame("chat client");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//text area
JScrollPane scrollPane = new JScrollPane(textArea);
//text field
JTextField MSGText = new JTextField(5);
//"send" button
JButton sMSGB = new JButton("send");
sMSGB.setPreferredSize(new Dimension(60, 30));
sMSGB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendMSG = MSGText.getText();
MSGText.setText("");
out.println("<" + Username + ">: " + sendMSG);
}
});
//panel
JPanel p = new JPanel();
p.setLayout((new BoxLayout(p, BoxLayout.PAGE_AXIS)));
p.add(Box.createVerticalStrut(5));
p.add(scrollPane);
p.add(Box.createVerticalStrut(5));
p.add(MSGText);
p.add(Box.createVerticalStrut(5));
p.add(sMSGB);
p.add(Box.createVerticalStrut(5));
frame.getContentPane().add(p);
//set frame visible
frame.pack();
frame.setVisible(true);
System.out.println("<Client>: opened stream");
while(sending) {
/*while((sendMSG = stdIn.readLine()) != null) {
out.println("<" + Username + ">: " + sendMSG);
}*/
while((getMSG = in.readLine()) != null) {
System.out.println(getMSG);
textArea.append(getMSG + "\n");
//sending = false;
}
}
//sending = true;
}
}
}
服务器:
public class Server {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(1011)) {
boolean listening = true;
while(listening) {
Socket socket = serverSocket.accept();
List<PrintWriter> outs = new CopyOnWriteArrayList<PrintWriter>();
new ServerThread(socket, outs).start();
System.out.println("opened thread");
}
} catch(IOException e) {
e.printStackTrace();
}
}
}
ServerThread:
public class ServerThread extends Thread {
private final Socket socket;
private final List<PrintWriter> outs;
public ServerThread(Socket socket, List<PrintWriter> outs) {
super("ServerThread");
this.socket = socket;
this.outs = outs;
System.out.println("Opened outs: " + outs.size());
}
private void sendToAll(String msg) {
for(PrintWriter out: outs) {
out.println(msg);
}
}
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
System.out.println("stream opened");
outs.add(out);
String getMSGs;
while((getMSGs = in.readLine()) != null) {
//out.println(getMSGs);
sendToAll(getMSGs);
System.out.println("msg received and sent");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
希望您能提供帮助。预先感谢
答案 0 :(得分:0)
每次新客户端连接时,您都将重新初始化outs
:
while(listening) {
Socket socket = serverSocket.accept();
List<PrintWriter> outs = new CopyOnWriteArrayList<PrintWriter>();
new ServerThread(socket, outs).start();
System.out.println("opened thread");
}
,并且基本上生成带有空outs
的线程。您需要将输出流(或套接字)的列表保留在循环之外,并构建一种在更新outs
列表时(当有新的客户端连接时)发信号通知已经存在的线程的方法。