我的这个聊天程序为什么不能在用户列表和聊天内容中看到信息???
package pro.chat;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
import javax.swing.*;
import javax.swing.border.TitledBorder;
/**
 * 聊天室的客户端程序,GUI 界面
 */
public class ChatClient extends JFrame implements ActionListener{
//登陆聊天室的名字标签和输入框
JLabel nameLabel=new JLabel();
JTextField nameTextField=new JTextField(15);
//连接和断开连接的按钮
JButton connectButton=new JButton();
JButton disConnectButton=new JButton();
JTextArea chatContentTextArea=new JTextArea(9,30);//聊天室内容的文本域
JButton sendMsgButton =new JButton();//发送消息的按钮
JTextField msgTextField=new JTextField(20);//消息输入框
JLabel msglabel=new JLabel();
java.awt.List peopleList=new java.awt.List(10);//聊天室用户列表
//以下定义数据流和网络变量
Socket soc=null;
PrintStream ps=null;
//客户端侦听服务器消息的线程
ClentListener listener=null;
public ChatClient(){
init();
}
//初始化图形界面
public void init(){
this.setTitle("聊天室客户端");
//初始化按钮和标签
nameLabel.setText("姓名");
connectButton.setText("连接");
connectButton.addActionListener(this);
disConnectButton.setText("断开");
disConnectButton.addActionListener(this);
//设置聊天内容不可编辑
chatContentTextArea.setEditable(false);
sendMsgButton.setText("发送");
sendMsgButton.addActionListener(this);
msgTextField.setText("请输入聊天信息");
//panel1放置输入姓名和连接两个按钮
JPanel panel1=new JPanel();
panel1.setLayout(new FlowLayout());
panel1.add(nameLabel);
panel1.add(nameTextField);
panel1.add(connectButton);
panel1.add(disConnectButton);
//用于放置聊天信息显示和聊天人员列表
JPanel panel2=new JPanel();
panel2.setLayout(new FlowLayout());
JScrollPane panel=new JScrollPane(chatContentTextArea);
panel.setBorder(new TitledBorder(BorderFactory.createEtchedBorder(Color.white,new Color(134,134,134)),"聊天内容"));
panel2.add(panel);
JScrollPane pane2=new JScrollPane(peopleList);
pane2.setBorder(new TitledBorder(BorderFactory.createEtchedBorder(Color.white,new Color(134,134,134)),"用户列表"));
panel2.add(pane2);
//用于放置发送信息区域
JPanel panel3=new JPanel();
panel3.setLayout(new FlowLayout());
panel3.add(msglabel);
panel3.add(msgTextField);
panel3.add(sendMsgButton);
//将组件添加到界面
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(panel1,BorderLayout.NORTH);
this.getContentPane().add(panel2,BorderLayout.CENTER);
this.getContentPane().add(panel3,BorderLayout.SOUTH);
this.pack();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//关闭聊天室客户端事件
protected void processWindowEvent(WindowEvent e){
super.processWindowEvent(e);
if(e.getID()==WindowEvent.WINDOW_CLOSING){
//如果是关闭聊天室客户端,则断开连接
disconnect();
dispose();
System.exit(0);
}
} //处理按钮事件
public void actionPerformed(ActionEvent event) {
Object source=event.getSource();
if(source==connectButton){
//如果点击连接按钮
if(soc==null){
try {
//使用端口2525实例化一个本地套接字
soc=new Socket(InetAddress.getLocalHost(),Constants.SERVER_PORT);
System.out.println(soc);//在控制台打印实例化结果
ps=new PrintStream(soc.getOutputStream());//将ps指向soc的输出流
//定义一个字符缓冲存储发送信息
//其中INFO 为关键字,让服务器识别为连接信息
//将name和IP用“:”分开,在服务器端将用一个StringTokenizer类来读取数据
StringBuffer info=new StringBuffer(Constants.CONNECT_IDENTIFER).append(Constants.SEPERATOR);
String userinfo=nameTextField.getText()+Constants.SEPERATOR+InetAddress.getLocalHost().getHostAddress();
ps.println(info.append(userinfo));
ps.flush();
//将客户端线程实例化,并启动
listener=new ClentListener(this,nameTextField.getText(),soc);
listener.start();
}  catch (IOException e1) {
// TODO Auto-generated catch block
System.out.println("Error: "+e1);
disconnect();
}
}
}else if(source==disConnectButton){
//如果点击断开连接按钮
disconnect();
}else if(source==sendMsgButton){
//如果点击发送按钮
if(soc!=null){
//定义并实例化一个字符缓冲存储发送的聊天信息
StringBuffer msg=new StringBuffer(Constants.MSG_IDENTIFER).append(Constants.SEPERATOR);
//用打印流发送聊天信息
ps.println(msg.append(msgTextField.getText()));
ps.flush();
}
}
}
//断开与服务器的连接
public void disconnect(){
if(soc!=null){
try {
//用打印流发送QUIT信息通知服务器断开此次通信
ps.println(Constants.QUIT_IDENTIFER);
ps.flush();
soc.close();//关闭套接字
listener.toStop();
soc=null;
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Error: "+e);
}
}
} public static void main(String[] args) {
ChatClient client=new ChatClient();
client.setVisible(true); }
//客户端线程类用来监听服务器传来的信息
class ClentListener extends Thread{
String name=null;//存储客户端连接后的name信息
BufferedReader br=null;//客户端接受服务器数据的输入流
PrintStream ps=null;//实现从客户端发送数据到服务器的打印流
Socket socket=null;//存储客户端的socket信息
ChatClient parent=null;//存储当前运行的ChatClient实例
boolean running=true;
//构造方法
public ClentListener(ChatClient p,String n,Socket s){
//接受参数
parent=p;
name=n;
socket=s;
try {
//实例化两个数据流
br=new BufferedReader(new InputStreamReader(s.getInputStream()));
ps=new PrintStream(s.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Error: "+e);
parent.disconnect();
}
}
//停止侦听
public void toStop(){
this.running=false;
}
//线程运行方法
public void run(){
String msg=null;
while(running){
msg=null;
try {
//读取从服务器传来的消息
msg=br.readLine();
System.out.println("receive msg: "+msg);
}catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Error: "+e);
parent.disconnect();
}
//如果从服务器传来的信息为空则断开此次连接
if(msg==null){
parent.listener=null;
parent.soc=null;
parent.peopleList.removeAll();
running=false;
return;
}
//用StringTokenizer类来实现读取分段字符
StringTokenizer st=new StringTokenizer(msg,Constants.SEPERATOR);
//读取信息头即关键字用来识别是何种信息
String keyword=st.nextToken();
if(keyword.equals(Constants.PEOPLE_IDENTIFER)){
//如果是PEOPLE则是服务器发来的客户连接信息
//主要用刷新客户端的用户列表
parent.peopleList.removeAll();
//遍历st取得目前所连接的客户
while(st.hasMoreTokens()){
String str=st.nextToken();
parent.peopleList.add(str);
}
}else if(keyword.equals(Constants.MSG_IDENTIFER)){
//如果关键字是MSG则是服务器传来的聊天信息
//主要用来刷新客户聊天信息区将每个客户的聊天内容显示出来
String usr=st.nextToken();
parent.chatContentTextArea.append(usr);
parent.chatContentTextArea.append(st.nextToken("\0"));
parent.chatContentTextArea.append("\r\n");
}else if(keyword.equals(Constants.QUIT_IDENTIFER)){
//如果关键字是QUIT则是服务器关闭的信息,切断此次信息,切断此次连接
System.out.println("Quit");
try {
running=false;
parent.listener=null;
parent.soc.close();
parent.soc=null;
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Error: "+e);
}finally{
parent.soc=null;
parent.peopleList.removeAll();
}
break;
}
}
//清除用户列表
parent.peopleList.removeAll();
}
}
}

解决方案 »

  1.   

    package pro.chat;
    /**
     *定义聊天室程序中用到的常量
     */
    public class Constants {
    public static final int SERVER_PORT=2525;//服务器的端口号
    public static final int MAX_CLIENT=10;
    public static final String SEPERATOR=": ";//消息标识符与信息体之间的分隔符
    public static final String MSG_IDENTIFER="MSG";//消息信息的标识符
    public static final String PEOPLE_IDENTIFER="PEOPLE";//用户列表信息的标识符
    public static final String CONNECT_IDENTIFER="INFO";//连接服务器信息的标识符
    public static final String QUIT_IDENTIFER="QUIT";//退出信息标识符
    }
      

  2.   

    package pro.chat;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.event.*;
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.StringTokenizer;
    import java.util.Vector;
    import javax.swing.*;
    import javax.swing.border.TitledBorder;
    /**
     * 聊天室的服务器程序,GUI界面
     */
    public class ChatServer extends JFrame{
    static JLabel statusBar=new JLabel();//状态拦标签
    //显示客户端的连接信息的列表
    static java.awt.List connectInfoList=new java.awt.List(10);
    //保存当前处理客户端请求的处理器线程
    static Vector clientProcessors=new Vector(10);
    //当前线程数
    static int activeConnects=0;
    //构造方法
    public ChatServer(){
    init();
    try {
    //设置界面为系统默认外观
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    SwingUtilities.updateComponentTreeUI(this);
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    private void init(){
    this.setTitle("聊天室服务器");
    statusBar.setText(" ");
    //初始化菜单
    JMenu fileMenu=new JMenu();
    fileMenu.setText("文件");
    JMenuItem exitMenuItem=new JMenuItem();
    exitMenuItem.setText("退出");
    exitMenuItem.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e){
    exitActionPerformed(e);
    }
    });
    fileMenu.add(exitMenuItem);

    JMenuBar menuBar=new JMenuBar();
    menuBar.add(fileMenu);
    this.setJMenuBar(menuBar);
    //将组件进行布局
    JPanel jPanel1=new JPanel();
    jPanel1.setLayout(new BorderLayout());
    JScrollPane pane=new JScrollPane(connectInfoList);
    pane.setBorder(new TitledBorder(BorderFactory.createEtchedBorder(Color.white,new Color(134,134,134)),"客户端连接信息"));
    jPanel1.add(new JScrollPane(pane),BorderLayout.CENTER);

    this.getContentPane().setLayout(new BorderLayout());
    this.getContentPane().add(statusBar,BorderLayout.SOUTH);
    this.getContentPane().add(jPanel1,BorderLayout.CENTER);
    this.pack();
    }
    //退出菜单项事件
    public void exitActionPerformed(ActionEvent e){
    //向客户端发送断开连接信息
    sendMsgToClients(new StringBuffer(Constants.QUIT_IDENTIFER));
    closeAll();//关闭所有的连接
    System.exit(0);
    }
    //处理窗口关闭事件
    protected void processWindowEvent(WindowEvent e){
    super.processWindowEvent(e);
    if(e.getID()==WindowEvent.WINDOW_CLOSING){
    exitActionPerformed(null);
    }
    }
    //刷新聊天室,不断刷新clientProcessors制造最新的用户列表
    public static void notifyRoomPeople(){
    StringBuffer people=new StringBuffer(Constants.PEOPLE_IDENTIFER);
    for(int i=0;i<clientProcessors.size();i++){
    ClientProcessor c=(ClientProcessor)clientProcessors.elementAt(i);
    people.append(Constants.SEPERATOR).append(c.clientName);
    }
    //用sendClients方法向客户端发送用户列表的信息
    sendMsgToClients(people);
    }
    //向所有客户端群发消息
    public static synchronized void sendMsgToClients(StringBuffer msg){
    for(int i=0;i<clientProcessors.size();i++){
    ClientProcessor c=(ClientProcessor)clientProcessors.elementAt(i);
    System.out.println("send msg: "+msg);
    c.send(msg);
    }
    }
    //关闭所有连接
    public static void closeAll(){
    while(clientProcessors.size()>0){
    ClientProcessor c=(ClientProcessor)clientProcessors.firstElement();
    try {
    //关闭socket连接和处理线程
    c.socket.close();
    c.toStop();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    System.out.println("Error: "+e);
    }finally{
    clientProcessors.removeElement(c);
    }
    }
    }
    /**
     * 判断客户端是否合法
     * 不允许同一客户端重复登陆,所谓同一客户端是指IP和名字都相同
     */
    public static boolean checkClient(ClientProcessor newclient){
    if(clientProcessors.contains(newclient)){
    return false;
    }else{
    return true;
    }
    }
    /**
     * 断开某个连接,并且从连接列表中删除
     */
    public static void disconnect(ClientProcessor client){
    disconnect(client,true);
    }
    /**
     * 断开某个连接,根据要求决定是否从连接列表中删除
     */
    public static synchronized void disconnect(ClientProcessor client,boolean toRemoveFromList){
    try {
    connectInfoList.add(client.clientIP+"断开连接");
    ChatServer.activeConnects--;
    String constr="目前有"+ChatServer.activeConnects+"客户连接";
    statusBar.setText(constr);
    client.send(new StringBuffer(Constants.QUIT_IDENTIFER));
    client.socket.close();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    System.out.println("Error: "+e);
    }finally{
    if(toRemoveFromList){
    clientProcessors.removeElement(client);
    client.toStop();
    }
    }
    }
    public static void main(String[] args) {
    ChatServer chatServer1=new ChatServer();
    chatServer1.setVisible(true);
    System.out.println("Server starting ...");
    ServerSocket server=null;
    try {
    //服务器开始侦听
    server=new ServerSocket(Constants.SERVER_PORT);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    System.out.println("Error: "+e);
    System.exit(1);
    }
    while(true){
    //如果当前客户端数小于MAX_CLIENT个时接受连接请求
    if(clientProcessors.size()<Constants.MAX_CLIENT){
    Socket socket=null;
    try {
    //收到客户端的请求
    socket=server.accept();
    if(socket!=null){
    System.out.println(socket+"连接");
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    System.out.println("Error: "+e);
    }
    //定义并实例化一个ClientProcessor线程类,用于处理客户端的信息
    ClientProcessor c=new ClientProcessor(socket);
    if(checkClient(c)){
    clientProcessors.addElement(c);//添加到列表
    int connum=++ChatServer.activeConnects;
    //如果客户端合法则继续
    //在状态拦里显示连接数
    String constr="目前有"+connum+"客户连接";
    ChatServer.statusBar.setText(constr);
    //将客户socket信息写入List框
    ChatServer.connectInfoList.add(c.clientIP+"连接");
    c.start();
    notifyRoomPeople();//通知所有客户端用户列表发生变化
    }else{
    //如果客户端不合法
    c.ps.println("不允许重复登陆");
    disconnect(c,false);
    }
    }else{
    //如果客户端超过MAX_CLIENT个,则等待一段时间再尝试接受请求
    try {
    Thread.sleep(200);
    } catch (InterruptedException e) {
    }
    }
    }
    }
    }
      

  3.   

    /**
     * 处理客户端发送的请求的线程
     */
    class ClientProcessor extends Thread{
    Socket socket;//存储一个连接客户端的socket信息
    String clientName;//存储客户端的连接姓名
    String clientIP;//存储客户端的IP信息
    BufferedReader br;//用来实现接受从客户端发送的数据流
    PrintStream ps;//用来实现向客户端发送信息的打印流
    boolean running=true;
    //构造方法
    public ClientProcessor(Socket s){
    socket =s;
    try {
    //初始化输入输出流
    br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
    ps=new PrintStream(socket.getOutputStream());
    //读取收到的信息,第一条信息是客户端的名字、IP信息
    String clientInfo=br.readLine();
    //读取信息,根据信息分隔符解析消息
    StringTokenizer stinfo=new StringTokenizer(clientInfo,Constants.SEPERATOR);
    String head=stinfo.nextToken();
    if(head.equals(Constants.CONNECT_IDENTIFER)){
    if(stinfo.hasMoreTokens()){
    //关键字后的第二段数据是客户名信息
    clientName=stinfo.nextToken();
    }
    if(stinfo.hasMoreTokens()){
    // 关键字后的第三段数据是客户IP信息
    clientIP=stinfo.nextToken();
    }
    System.out.println(head);//在控制台打印头信息
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    System.out.println("Error: "+e);
    }
    }
    //向客护端发送信息
    public void send(StringBuffer msg){
    ps.println("msg");
    ps.flush();
    }
    //线程运行方法
    public void run(){
    while(running){
    String line=null;
    try {
    //读取客户端发来的信息流
    line=br.readLine();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    System.out.println("Error: "+e);
    ChatServer.disconnect(this);
    ChatServer.notifyRoomPeople();
    return;
    }
    //客户已离开
    if(line==null){
    ChatServer.disconnect(this);
    ChatServer.notifyRoomPeople();
    return;
    }
    StringTokenizer st=new StringTokenizer(line,Constants.SEPERATOR);
    String keyword=st.nextToken();
    //如果关键字是MSG则是客户端发来的聊天信息
    if(keyword.equals(Constants.MSG_IDENTIFER)){
    StringBuffer msg=new StringBuffer(Constants.MSG_IDENTIFER).append(Constants.SEPERATOR);
    msg.append(clientName);
    msg.append(st.nextToken("\0"));
    //再将某个客户发来的聊天信息发送到每个连接客户的聊天拦中
    ChatServer.sendMsgToClients(msg);
    }else if(keyword.equals(Constants.QUIT_IDENTIFER)){
    //如果关键字是QUIT则是客户端发来断开连接的信息
    ChatServer.disconnect(this);//服务器断开与这个客户的连接
    //继续监听聊天室并刷新其他客户的聊天人名列表
    ChatServer.notifyRoomPeople();
    running=false;
    }
    }
    }
    public void toStop(){
    running=false;
    }
    //覆盖Object类的equals方法
    public boolean equals(Object obj){
    if(obj instanceof ClientProcessor){
    ClientProcessor obj1=(ClientProcessor)obj;
    if(obj1.clientIP.equals(this.clientIP)&&(obj1.clientName.equals(this.clientName))){
    return true;
    }
    }
    return false;
    }
        //覆盖Object类的hashCode方法
    public int hashCode(){
    return(this.clientIP+Constants.SEPERATOR+this.clientName).hashCode();
    }
    }