这两天写JAVA实现局域网聊天室,在添加用户列表时遇到了问题
思路是:点击“登录”时发送用户信息,前面加上“!@#$”作标识符,服务器读到它就知道是用户信息,调用tellUserInfo方法
点击“发送”时,把聊天信息发送给服务器,服务器读到它就调用tellEveryone方法下面实现用户列表的代码,只有最后一个客户端的用户列表是正确的
看不出哪里的问题,帮忙看看,先谢啦import java.io.*;
import java.net.*;
import java.util.*;public class ChatServer {
// 定义一个ArrayList,存放所有客户端对应的输出流
private ArrayList<PrintWriter> writers;
PrintWriter writer;
BufferedReader reader;
String clientName,clientIP,clientInfo;
private ArrayList<String> userList = new ArrayList<String>(); // 存储用户的信息 clientInfo public void go() {
// 用一个ArrayList存放与所有客户端对应的输出流
writers = new ArrayList<PrintWriter>();
try {
// 定义一个ServerSocket对象
ServerSocket serverSock = new ServerSocket(6000); while(true) {
Socket socket = serverSock.accept();
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writers.add(writer); // 对于每个客户端,生成一个线程对象,来做专门的处理
Thread t = new Thread(new ClientHandler(socket));
t.start(); }
}catch(Exception ex) {
ex.printStackTrace();
}
} // 定义一个内部类,实现Runnable接口,以便用线程进行处理
public class ClientHandler implements Runnable {
// 字段定义 Socket socket;
public ClientHandler(Socket socket) {
try {
// 在构造器中指定针对客户端的输入流
this.socket = socket;
reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
} catch(Exception ex) {
ex.printStackTrace();
}
} // 实现run方法
public void run() {
String chatMsg = "",userInfo = "",str = "";
try {
str = reader.readLine();
if(str.equals("!@#$")){
userInfo = reader.readLine();
userList.add(userInfo);
tellUserInfo();
} } catch(Exception ex) {
ex.printStackTrace();
}
}
} // 向所有客户端发送信息
public void tellEveryone(String message) {
for(PrintWriter pt: writers){
pt.println(message);
pt.flush();
}
} public void tellUserInfo(){
Collections.sort(userList);
for( PrintWriter pt: writers ){
pt.println("!@#$");
for (int i = 0; i < userList.size(); i++) {
pt.println(userList.get(i));
}
pt.flush();
}
} public static void main(String[] args) {
new ChatServer().go(); // 服务器启动
}}
思路是:点击“登录”时发送用户信息,前面加上“!@#$”作标识符,服务器读到它就知道是用户信息,调用tellUserInfo方法
点击“发送”时,把聊天信息发送给服务器,服务器读到它就调用tellEveryone方法下面实现用户列表的代码,只有最后一个客户端的用户列表是正确的
看不出哪里的问题,帮忙看看,先谢啦import java.io.*;
import java.net.*;
import java.util.*;public class ChatServer {
// 定义一个ArrayList,存放所有客户端对应的输出流
private ArrayList<PrintWriter> writers;
PrintWriter writer;
BufferedReader reader;
String clientName,clientIP,clientInfo;
private ArrayList<String> userList = new ArrayList<String>(); // 存储用户的信息 clientInfo public void go() {
// 用一个ArrayList存放与所有客户端对应的输出流
writers = new ArrayList<PrintWriter>();
try {
// 定义一个ServerSocket对象
ServerSocket serverSock = new ServerSocket(6000); while(true) {
Socket socket = serverSock.accept();
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writers.add(writer); // 对于每个客户端,生成一个线程对象,来做专门的处理
Thread t = new Thread(new ClientHandler(socket));
t.start(); }
}catch(Exception ex) {
ex.printStackTrace();
}
} // 定义一个内部类,实现Runnable接口,以便用线程进行处理
public class ClientHandler implements Runnable {
// 字段定义 Socket socket;
public ClientHandler(Socket socket) {
try {
// 在构造器中指定针对客户端的输入流
this.socket = socket;
reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
} catch(Exception ex) {
ex.printStackTrace();
}
} // 实现run方法
public void run() {
String chatMsg = "",userInfo = "",str = "";
try {
str = reader.readLine();
if(str.equals("!@#$")){
userInfo = reader.readLine();
userList.add(userInfo);
tellUserInfo();
} } catch(Exception ex) {
ex.printStackTrace();
}
}
} // 向所有客户端发送信息
public void tellEveryone(String message) {
for(PrintWriter pt: writers){
pt.println(message);
pt.flush();
}
} public void tellUserInfo(){
Collections.sort(userList);
for( PrintWriter pt: writers ){
pt.println("!@#$");
for (int i = 0; i < userList.size(); i++) {
pt.println(userList.get(i));
}
pt.flush();
}
} public static void main(String[] args) {
new ChatServer().go(); // 服务器启动
}}
import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;public class ChatClient {
JTextField jtf_name,jtf_ip; // LoginGUI组件
JTextField jtf_filePath,jtf_userSlectForFileSend; // FileSendGUI组件
JTextArea jta_incoming = new JTextArea(),
jta_outgoing = new JTextArea(),
jta_userInfo = new JTextArea(); // ClientGUI组件
BufferedReader reader; // 缓冲区流(用来读取文本信息)
PrintWriter writer; // 输出文本信息的流
Socket socket; // socket
String clientName,clientIP,clientInfo; // 客户端的名字和它设置的服务器ip地址
LoginGUI loginGUI; //构建登陆界面
ClientGUI clientGUI; //构建客户端界面
public void go() {
// 用Swing构建一个客户端的界面
loginGUI = new LoginGUI();
// 调用自定义的setUpNetworking方法设定网络连接
setUpNetworking(); // 开启一个线程来处理信息的读取 start后开始等待从服务器返回的流
Thread readerThread = new Thread(new msgReader());
readerThread.start(); } private void setUpNetworking() {
try {
// 设定网络连接,准备好用于输入、输出文本信息的“流对象”
socket = new Socket(clientIP,6000);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter(socket.getOutputStream());
System.out.println("网络连接建立完毕!"); } catch (IOException ex) {
ex.printStackTrace();
}
} // 实现Runnable接口,以便用线程进行处理
public class msgReader implements Runnable {
// 实现run方法
public void run() {
String userInfo = "",chatMsg = "",str = "";
try {
str = reader.readLine();
if(str.equals("!@#$")){
jta_userInfo.setText("");
while((userInfo = reader.readLine()) != null){
jta_userInfo.append(userInfo + "\n");
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
} public class jb_sendButtonListener implements ActionListener {
// 实现actionPerformed方法
public void actionPerformed(ActionEvent ae) {
try {
// 当用户按下“发送”按钮时,就把文本框中的文本写到网络流中
writer.println(clientName + "说:\n" + jta_outgoing.getText());
writer.flush(); } catch(Exception ex) {
ex.printStackTrace();
}
// 清空文本框,以便录入新的信息
jta_outgoing.setText("");
}
} public class jb_loginListener implements ActionListener{
public void actionPerformed(ActionEvent e){
clientName = jtf_name.getText();
clientIP = socket.getLocalAddress().toString();
clientInfo = clientName + clientIP;
writer.println("!@#$");
writer.println(clientInfo);
writer.flush(); loginGUI.setVisible(false);
clientGUI = new ClientGUI(); }
}
public class ClientGUI extends JFrame{ JPanel jp1,jp2,jp3,jp4,jp5,jp6,jp7,jp8;
JScrollPane jp9,jp10,jp11;
JButton jb_send,jb_quit,jb_file,jb_pic,jb_chat;
JLabel jl; public ClientGUI(){
this.setTitle("局域网聊天室");
jp1 = new JPanel();
jp2 = new JPanel();
jp3 = new JPanel();
jp4 = new JPanel();
jp5 = new JPanel();
jp6 = new JPanel();
jp7 = new JPanel();
jp8 = new JPanel(); jp1.setLayout(new BorderLayout());
jp2.setLayout(new BorderLayout());
jp3.setLayout(new BorderLayout());
jp4.setLayout(new BorderLayout());
jp8.setLayout(new BorderLayout());
jp5.setLayout(new FlowLayout(FlowLayout.RIGHT));
jp6.setLayout(new FlowLayout(FlowLayout.RIGHT)); jta_incoming = new JTextArea();
jta_outgoing = new JTextArea(4,28);
//jta_userInfo = new JTextArea();
jta_incoming.setEditable(false);
jta_userInfo.setEditable(false); jp9 = new JScrollPane(jta_incoming);
jp10 = new JScrollPane(jta_outgoing);
jp11 = new JScrollPane(jta_userInfo);
jb_send = new JButton("发送");
jb_quit = new JButton("关闭");
jb_file = new JButton("传送文件");
jb_pic = new JButton("接收文件");
jb_chat = new JButton("私聊");
jb_send.setSize(80,20);
jb_quit.setSize(80,20);
jb_file.setSize(80,20);
jb_pic.setSize(80,20); //发送按钮注册监听器
jb_send.addActionListener(new jb_sendButtonListener());
//文件发送按钮注册监听器
//jb_file.addActionListener(new jb_fileSendButtonListener());
//私聊按钮注册监听器
//jb_chat.addActionListener(new jb_chatButtonListener()); jl = new JLabel("用户列表 "); jp2.add(jp9,BorderLayout.CENTER);
jp2.add(jp3,BorderLayout.SOUTH); jp3.add(jp5,BorderLayout.NORTH);
jp3.add(jp10,BorderLayout.CENTER);
jp3.add(jp6,BorderLayout.SOUTH); jp5.add(jb_file);
jp5.add(jb_pic);
jp5.add(jb_chat); jp6.add(jb_send);
jp6.add(jb_quit); jp8.add(jl,BorderLayout.NORTH);
jp8.add(jp11,BorderLayout.CENTER); jp4.add(jp8,BorderLayout.CENTER);
jp4.add(jp7,BorderLayout.WEST); jp1.add(jp2,BorderLayout.CENTER);
jp1.add(jp4,BorderLayout.EAST); this.add(jp1); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(200,100,600,500);
this.setVisible(true);
} } public class FileSendGUI extends JFrame{
JPanel jp1,jp2,jp3,jp4; GridLayout gl;
JLabel jl1,jl2;
JButton jb_send,jb_quit; public FileSendGUI(){
jp1 = new JPanel(); gl = new GridLayout(3,1);
jp1.setLayout(gl);
jp2 = new JPanel(); jp3 = new JPanel(); jp4 = new JPanel();
jp1.add(jp2); jp1.add(jp3); jp1.add(jp4); jl1 = new JLabel("输入文件完整路径:"); jl2 = new JLabel("输入用户名(ALL为所有人):");
jtf_filePath = new JTextField(20); jtf_userSlectForFileSend = new JTextField(20);
jb_send = new JButton("发送"); jb_quit = new JButton("取消"); jp2.add(jl1); jp2.add(jtf_filePath);
jp3.add(jl2); jp3.add(jtf_userSlectForFileSend);
jp4.add(jb_send); jp4.add(jb_quit); this.add(jp1); this.setBounds(300,250,300,200);
this.setVisible(true); }
} public class ChatSelectGUI extends JFrame{
JPanel jp1,jp2,jp3,jp4; GridLayout gl;
JLabel jl1,jl2;
JTextField jtf1,jtf2;
JButton jb_send,jb_quit; public ChatSelectGUI(){
jp1 = new JPanel(); gl = new GridLayout(2,1);
jp1.setLayout(gl);
jp2 = new JPanel(); jp3 = new JPanel();
jp1.add(jp2); jp1.add(jp3); jl1 = new JLabel("输入对方用户名:"); jtf1 = new JTextField(16);
jb_send = new JButton("确定"); jb_quit = new JButton("取消"); jp2.add(jl1); jp2.add(jtf1);
jp3.add(jb_send); jp3.add(jb_quit); this.add(jp1); this.setBounds(300,250,300,200);
this.setVisible(true);
} } public class LoginGUI extends JFrame{
JPanel jp1,jp2,jp3,jp4; GridLayout gridLayout;
JLabel jl1,jl2;
JButton jb_login,jb_quit;
public LoginGUI(){
jp1 = new JPanel(); jp2 = new JPanel(); jp3 = new JPanel();
jp4 = new JPanel(); gridLayout = new GridLayout(3,1);
jl1 = new JLabel("输入你的昵称:"); jl2 = new JLabel("服务器的地址:");
jtf_name = new JTextField(10);jtf_ip = new JTextField(10);
jb_login = new JButton("登录"); jb_quit = new JButton("取消");
jp1.setLayout(gridLayout);
this.getContentPane().add(jp1);
jp1.add(jp2);jp1.add(jp3);jp1.add(jp4);
jp2.add(jl1);jp2.add(jtf_name);
jp3.add(jl2);jp3.add(jtf_ip);
jp4.add(jb_login);jp4.add(jb_quit); //登录按钮注册监听器,启动客户端界面
jb_login.addActionListener(new jb_loginListener()); this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setBounds(350, 250, 300, 200);
}
} public static void main(String[] args){
ChatClient client = new ChatClient();
client.go();
}
}
xie xie lou zu le
use// 定义一个内部类,实现Runnable接口,以便用线程进行处理
public class ClientHandler implements Runnable {
// 字段定义 Socket socket;
public ClientHandler(Socket socket) {
try {
// 在构造器中指定针对客户端的输入流
this.socket = socket;
reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
} catch(Exception ex) {
ex.printStackTrace();
}
} // 实现run方法
public void run() {
String chatMsg = "",userInfo = "",str = "";
try {
str = reader.readLine();
if(str.equals("!@#$")){
userInfo = reader.readLine(); //问题
userList.add(userInfo); //问题
tellUserInfo(); //问题
} } catch(Exception ex) {
ex.printStackTrace();
}
}
}
rList是动态增加的,例如第一个客户端登录,你只把第一个客户信息发给他
第二个客户端登录的时候,你发送的是第一个和第二个的信息,以此类推,只有最后的客户端
用户列表是正确的
可以这样做:
在所有的客户端都连接了之后,在发送用户列表,
或者没隔几秒钟发送用户列表,