因为不能上传文件,我的项目文件也就无法上传,所以我只好一个一个地贴上来。
    这个程序要求用数据库来存储user和password,如果没有数据库和jdbc驱动程序,就要把我的代码改动一下,用文档存储方式,只不过这些我注释掉了。
   先发个建表的脚本:
create table chatUsers
(
 p_name  char(20),
 p_password char(20)
)
select * from chatUsersjava程序有三个文件,一个是客户端的,一个是服务器端,还有一个是数据库连接的。第一个:AppClient.javapackage com;
import javax.net.SocketFactory;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.util.*;public class AppClient extends JFrame implements ActionListener
{
JPanel pnlLogin, pnlChat;

JLabel lblIPAddress, lblName, lblPassword;

JTextArea taViewTalk;

JLabel lblMsg, lblUsers;

JTextField txtMsg, txtIPAddress, txtUserName;  
JPasswordField pswPassword;

JButton btnSend, btnLogin, btnRegister;
    JComboBox cmbUsers;

GridBagLayout gbl;
GridBagConstraints gbc;

JDialog dialogLogin=new JDialog(this,"Login",true);

Socket socket;    BufferedReader in;
    PrintWriter out;
    
    String strSend, strReceive, strKey, strStatus;
    private StringTokenizer st; public AppClient(String str)
{
super(str);
//初始化
socket=new Socket();

gbl = new GridBagLayout();
gbc = new GridBagConstraints();
pnlLogin = new JPanel();
pnlLogin.setLayout(gbl);
            
         //初始化控件 
        lblIPAddress = new JLabel("Server IP:");
lblName = new JLabel("UserName:");
lblPassword = new JLabel("Password:");

txtIPAddress = new JTextField("127.0.0.1",12);
txtUserName = new JTextField(12);
        pswPassword = new JPasswordField(12);
        
        btnLogin=new JButton("Login");
        btnSend = new JButton("Send");
        btnRegister =new JButton("Register");
        
        lblMsg = new JLabel("Message");
        lblUsers = new JLabel("To");
        
        txtMsg = new JTextField(30);
        
        pnlChat = new JPanel();
        
        taViewTalk = new JTextArea(18,40);
        
        cmbUsers = new JComboBox();
        
        btnLogin.addActionListener(this);
        btnSend.addActionListener(this);
        btnRegister.addActionListener(this);
        
        cmbUsers.addItem("All");
        
    pnlChat.add(lblMsg);
        pnlChat.add(txtMsg);
        pnlChat.add(lblUsers);
        pnlChat.add(cmbUsers);
        pnlChat.add(btnSend);

getContentPane().add("Center",taViewTalk);
getContentPane().add("South",pnlChat);
btnSend.setEnabled(false);
taViewTalk.setEditable(false);
setSize(600,450);
setVisible(true);


// 登录对话框初始化
dialogLogin.getContentPane().setLayout(new FlowLayout());
dialogLogin.getContentPane().add(lblIPAddress);
dialogLogin.getContentPane().add(txtIPAddress);
dialogLogin.getContentPane().add(lblName);
dialogLogin.getContentPane().add(txtUserName);
dialogLogin.getContentPane().add(lblPassword);
dialogLogin.getContentPane().add(pswPassword);
dialogLogin.getContentPane().add(btnLogin);
dialogLogin.getContentPane().add(btnRegister);

dialogLogin.setBounds(300,300,250,200);
dialogLogin.setVisible(true);

    }

public static void main(String[] args)
{
new AppClient("Chatroom");
}

//建立与服务端通信的套接字
void connectServer()
{
try
{
InetAddress address=InetAddress.getByName(txtIPAddress.getText());
InetSocketAddress socketAddress=new InetSocketAddress(address,10001);
socket.connect(socketAddress);
// socket=new Socket(txtIPAddress.getText(),10001); 

in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
     out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
}
catch(ConnectException e)
{
    JOptionPane.showMessageDialog(this,"Connect server fail!","ERROE",JOptionPane.INFORMATION_MESSAGE);
    txtIPAddress.grabFocus();
    System.out.println(e);
}
catch(Exception e)
{
System.out.println(e);
e.printStackTrace();
}
}

// 弹出窗口
public void popWindows(String strWarning,String strTitle)
{
JOptionPane.showMessageDialog(this,strWarning,strTitle,JOptionPane.INFORMATION_MESSAGE);
}

private void initLogin() throws IOException
{
strReceive = in.readLine();
        st = new StringTokenizer(strReceive,"|");
       strKey = st.nextToken();
    
     if(strKey.equals("login"))
{
     strStatus = st.nextToken();
     if(strStatus.equals("succeed"))
{
     btnLogin.setEnabled(false);
          btnSend.setEnabled(true);
           pnlLogin.setVisible(false);
           dialogLogin.dispose();
            new ClientThread(in);
            out.println("init|online");
        }
        popWindows(strKey+" "+strStatus+"!","Login");
        }
        
        if(strKey.equals("warning"))
{
         strStatus = st.nextToken();
         popWindows(strStatus,"Register");
        }
}
 
    public void actionPerformed(ActionEvent evt)
    {
Object source=evt.getSource();
try
{
         if(source==btnLogin)
{
             if((txtIPAddress.getText().length()>0)&&(txtUserName.getText().length()>0)&&(pswPassword.getText().length()>0))
{
     connectServer();
strSend = "login|"+txtUserName.getText()+"|"+String.valueOf(pswPassword.getPassword());
out.println(strSend);
initLogin();
}
else
{
popWindows("Pls input information entirely!","ERROE");
}
        }
        else if(source==btnRegister)
{
       if((txtUserName.getText().length()>0)&&(pswPassword.getText().length()>0))
{
       connectServer();
       strSend="reg|"+txtUserName.getText()+"|"+String.valueOf(pswPassword.getPassword());
       out.println(strSend);
       initLogin();
       }
       }
      
       else if(source==btnSend)
{
     if(txtMsg.getText().length()>0)
{
       out.println("talk|"+txtMsg.getText()+"|"+txtUserName.getText()+"|"+cmbUsers.getSelectedItem().toString());
       txtMsg.setText("");
       txtMsg.grabFocus();
}
       }
    }
catch(Exception e)
{
System.out.println(e);
}
}
   
    class ClientThread implements Runnable
    {
//    private Socket sot=null;
        private BufferedReader cin;
     //   private PrintWriter out;
        private String cstrReceive, cstrKey; 
        private Thread threadTalk;
        private StringTokenizer cst;   
        
    public ClientThread(BufferedReader in) throws IOException
    {
//    this.sot = s;
//    cin = new BufferedReader(new InputStreamReader(sot.getInputStream()));
    cin=in;
        
//    this.cstrReceive=strReceive;
    threadTalk = new Thread(this);
    threadTalk.start();
    }
   
    public void run()
    {
    while(true)
    {
    synchronized(this)
    {
    try
    {
    cstrReceive = cin.readLine();
    cst = new StringTokenizer(cstrReceive,"|");
         cstrKey = cst.nextToken();
    if(cstrKey.equals("talk"))
    {
    String strTalk = cst.nextToken();
    strTalk =taViewTalk.getText()+"\r\n   "+strTalk;
    taViewTalk.setText(strTalk);
    }
    else if(cstrKey.equals("online"))
    {
    String strOnline;
    while(cst.hasMoreTokens())
    {
    strOnline=cst.nextToken();
    cmbUsers.addItem(strOnline);
    }
    }
    else if(cstrKey.equals("remove"))
    {
    String strRemove;
    while(cst.hasMoreTokens())
    {
    strRemove=cst.nextToken();
    cmbUsers.removeItem(strRemove);
    }
    }
    else if(cstrKey.equals("warning"))
    {
    String strWarning = cst.nextToken();
    popWindows(strWarning,"Warning");
    }
    Thread.sleep(1000);
    }
    catch(Exception e)
    {
    e.printStackTrace();
    }
    }
    }
    }
    }
}

解决方案 »

  1.   

    第二个:AppServer.javapackage com;import java.io.*;
    import java.net.*;
    import java.sql.ResultSet;
    import java.util.*;public class AppServer
    {
    ServerSocket serverSocket; // 创建服务器端套接字
    Socket socket;
        public AppServer()
    {
         try
    {
         serverSocket=new ServerSocket(10001); // 启动服务
         System.out.println("Server started...");
         getIP(); // 得到并显示服务器端IP
       
        while(true)
    {
         socket=serverSocket.accept();// 监听客户端的连接请求,并返回客户端socket
        new ServerThread(socket); // 创建一个新线程来处理与该客户的通讯
        }
        }
        catch(IOException e)
    {
           System.out.println("[ERROR] Cound not start server."+e);
        }
    } // 得到服务器IP地址并显示
    public void getIP()
    {
       try
    {
       InetAddress localAddress = InetAddress.getLocalHost();
       byte[] ipAddress = localAddress.getAddress();
       System.out.println("Server IP is:"+(ipAddress[0]&0xff)+"."+(ipAddress[1]&0xff)+"."+
       (ipAddress[2]&0xff)+"."+(ipAddress[3]&0xff));
       }
       catch(Exception e)
    {
       System.out.println("[ERROR] Cound not get IP."+e);
       }
    }
      
    // 实例化服务器端程序
    public static void main(String args[])
    {
    new AppServer();
    }
    }class ServerThread extends Thread
    {
    private Socket ssocket;//定义客户端套接字
        private BufferedReader in;// 定义输入流
        private PrintWriter out;// 定义输出流
        private static Vector onlineUser = new Vector(10,5);
        private static Vector socketUser = new Vector(10,5);
        private String strReceive, strKey;
        private StringTokenizer st;
        private final String USERLIST_FILE = "user.txt"; //设定存放用户信息的文件
    UserDAO dao;
    public ServerThread(Socket client) throws IOException
    {
       ssocket = client;
       in=new BufferedReader(new InputStreamReader(ssocket.getInputStream())); //客户端接收
       out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(ssocket.getOutputStream())),true);//客户端输出
        dao=new UserDAO();
       this.start();
        }
         
       public void run()
    {
       try
    {
    while(true)
    {
           strReceive = in.readLine();//从服务器端接收一条信息后拆分、解析,并执行相应操作
           st = new StringTokenizer(strReceive,"|");
           strKey = st.nextToken();
         if(strKey.equals("login"))
    {
          login();
           }
            else if(strKey.equals("talk"))
    {
            talk();
            }
            else if(strKey.equals("init"))
    {
            initClientOnline();
            }
            else if(strKey.equals("reg"))
    {
            register();
            }
            }
    }
            catch(IOException e)

    //用户关闭客户端造成此异常,关闭该用户套接字。
            String leaverUser = closeSocket();
          System.out.println("[SYSTEM] "+leaverUser+" leave JAVA chatroom!");
          sendAll("talk|***"+leaverUser+" leave JAVA chatroom!***");
          e.printStackTrace();
        }
    }

    // 判断是否有该注册用户
    private boolean isExistUser(String name)
    {
    // String strRead;
    try
    {
    // FileInputStream inputfile = new FileInputStream(USERLIST_FILE);
    //      //create input stream
    //      DataInputStream inputdata=new DataInputStream(inputfile);
    //      while((strRead=inputdata.readLine())!=null)
    // {
    //      StringTokenizer stUser = new StringTokenizer(strRead,"|");
    //      if(stUser.nextToken().equals(name))
    // {
    //      return true;
    //      }
    //      }
    ResultSet rs=dao.queryUserFromName(name);
    if(rs.next()){
    return true;
    }
    }
    catch(Exception e)
    {
    System.out.println("[ERROR]"+e);
    out.println("warning|Read file error!");
    }
    return false;
    }

    // 判断用户的用户名密码是否正确
    private boolean isUserLogin(String name,String password)
    {
    // String strRead;
    try
    {
    // FileInputStream inputfile = new FileInputStream(USERLIST_FILE);
    //     //create input stream
    //     DataInputStream inputdata=new DataInputStream(inputfile);
    //     
    //      while((strRead=inputdata.readLine())!=null)
    // {
    //      if(strRead.equals(name+"|"+password))
    // {
    //      return true;
    //      }
    //      }
    ResultSet rs=dao.queryUserFromName(name);
        if(rs.next()){
    if((rs.getString("p_name").trim()).equals(name) && (rs.getString("p_password").trim()).equals(password)){
    return true;
    }
        }
    }
    catch(Exception e)
    {
    System.out.println("[ERROR]"+e);
    out.println("warning|Read file error!");
    }
    return false;
    }
    // 用户注册
    private void register() throws IOException
    {
    String name = st.nextToken(); //得到用户名称
    String password = st.nextToken().trim();//得到用户密码
    if(isExistUser(name))
    {
    System.out.println("[ERROR] "+name+" Register fail!");
    out.println("warning|The Username has existed!");
    }
    else
    {
    // RandomAccessFile userFile=new RandomAccessFile(USERLIST_FILE,"rw");
    //         userFile.seek(userFile.length()); // 在文件尾部加入新用户信息
    //         userFile.writeBytes(name+"|"+password+"\r\n");
    dao.insertUser(name, password);
            longin(name); //自动登陆聊天室
    }
    }

    // 用户登录(从登录框直接登陆)
    private void login() throws IOException
    {
    String name = st.nextToken(); //得到用户名称
    String password = st.nextToken().trim();//得到用户密码
    boolean succeed = false;

    System.out.println("[USER LOGIN] "+name+":"+password+":"+ssocket); for(int i=0;i<onlineUser.size();i++)
    {
    if(onlineUser.elementAt(i).equals(name))
    {
    System.out.println("[ERROR] "+name+" is logined!");
    out.println("warning|"+name+"has logined!");
    }
    }
    if(isUserLogin(name,password))
    {
    // 判断用户名和密码
          longin(name);
          succeed = true;
          }
          if(!succeed)
    {
          out.println("warning|"+name+"login fail!");
          System.out.println("[SYSTEM] "+name+" login fail!");
          }
         
    }

    // 用户登录
    private void longin(String name) throws IOException
    {
    out.println("login|succeed");
          sendAll("online|"+name);
          onlineUser.addElement(name);
          socketUser.addElement(ssocket);
          sendAll("talk|***Welcom "+name+" to JAVA chatroom!***");
          System.out.println("[SYSTEM] "+name+" login succeed!");
    }

    // 聊天信息处理
    private void talk() throws IOException
    {
    String strTalkInfo = st.nextToken(); //得到聊天内容;
    String strSender = st.nextToken();  //得到发消息人
    String strReceiver = st.nextToken(); //得到接收人
    System.out.println("[TALK_"+strReceiver+"] "+strTalkInfo);
    Socket socketSend;
    PrintWriter outSend;

    // 得到当前时间
    GregorianCalendar calendar = new GregorianCalendar();
    String strTime = "("+calendar.get(Calendar.HOUR)+":"+calendar.get(Calendar.MINUTE)+":"+calendar.get(Calendar.SECOND)+")";
    strTalkInfo +=strTime;
     
    if(strReceiver.equals("All"))
    {
    sendAll("talk|"+strSender+" talk to everyone:"+strTalkInfo);
    }
    else
    {
    if(strSender.equals(strReceiver))
    {
    out.println("talk|***Can't talk to yourself!");
    }
    else
    {
    for(int i=0;i<onlineUser.size();i++)
    {
    if(strReceiver.equals(onlineUser.elementAt(i)))
    {
    socketSend = (Socket)socketUser.elementAt(i);
    outSend = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socketSend.getOutputStream())),true);
    outSend.println("talk|"+strSender+" talk to you:"+strTalkInfo);
    }
    else if(strSender.equals(onlineUser.elementAt(i)))
    {
    socketSend = (Socket)socketUser.elementAt(i);
    outSend = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socketSend.getOutputStream())),true);
    outSend.println("talk|you to "+strReceiver+":"+strTalkInfo);
    }
    }
    }
    }
    }

    // 初始化在线用户列表
    private void initClientOnline() throws IOException

    String strOnline = "online";
    for(int i=0;i<onlineUser.size();i++)
    {
    strOnline += "|"+onlineUser.elementAt(i);
    }
    out.println(strOnline);
    }

    // 信息群发
    private void sendAll(String strSend)
    {
    Socket socketSend;
    PrintWriter outSend;
    try
    {
    for(int i=0;i<socketUser.size();i++)
    {
    socketSend = (Socket)socketUser.elementAt(i);
    outSend = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socketSend.getOutputStream())),true);
    outSend.println(strSend);
    }
    }
            catch(IOException e)
    {
          System.out.println("[ERROR] send all fail!");
            }
    }

    // 关闭套接字,并将用户信息从在线列表中删除
    private String closeSocket()
    {
    String strUser = "";
    for(int i=0;i<socketUser.size();i++)
    {
    if(ssocket.equals((Socket)socketUser.elementAt(i)))
    {
    strUser = onlineUser.elementAt(i).toString();
    socketUser.removeElementAt(i);
    onlineUser.removeElementAt(i);
    sendAll("remove|"+strUser);
    }
    }
    try
    {
    in.close();
          out.close();
          ssocket.close();
          }
    catch(IOException e)
    {
         System.out.println("[ERROR] "+e);
        }
    return strUser;
    }
    }
      

  2.   

    第三个:UserDAO.javapackage com;
    import java.sql.*;//PreparedStatement的好处
    //1、因为是预编译的,所以性能好
    //2、防止sql 注入,安全性好
    //3、代码清晰,容易维护
    public class UserDAO {
    Connection connection=null;

    public UserDAO(){
    try{
    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    connection = DriverManager
    .getConnection("jdbc:sqlserver://localhost;databaseName=AdventureWorks;user=sa;password=sh-niit"); }catch(Exception e){
    e.printStackTrace();
    throw new RuntimeException(e.getMessage());
    }
    }

    public Connection getConnection() throws SQLException{
    if(connection==null || connection.isClosed()){
    try{
    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    connection = DriverManager
    .getConnection("jdbc:sqlserver://localhost;databaseName=AdventureWorks;user=sa;password=sh-niit"); }catch(Exception e){
    e.printStackTrace();
    throw new RuntimeException(e.getMessage());
    }
    }

    return connection;
    }

    public void insertUser(String name,String password){
    try{
    String sql="insert chatUsers values(?,?)";//问号表示占位符
    PreparedStatement stat=this.getConnection().prepareStatement(sql);
    stat.setString(1, name);
    stat.setString(2, password);//1表示第一个问号


    int result=stat.executeUpdate();
    System.out.println(result+" row inserted");
    }catch(SQLException se){
    se.printStackTrace();
    }
    }



    // public ResultSet  queryUser(){
    // ResultSet rs=null;
    // try{
    // String sql="Select * from chatUsers ";
    // PreparedStatement stat=this.getConnection().prepareStatement(sql);
    // rs=stat.executeQuery();
    // System.out.println(" queryUser ");
    //
    // }catch(SQLException e){
    // e.printStackTrace();
    // }
    // return rs;
    // }

    public ResultSet  queryUserFromName(String name){
    ResultSet rs=null; try{
    String sql="Select * from chatUsers where p_name = ?";
    PreparedStatement stat=this.getConnection().prepareStatement(sql);
    stat.setString(1,name);
    rs=stat.executeQuery();
    System.out.println(" row finded");
    }catch(SQLException e){
    e.printStackTrace();
    }
    return rs;
    }

    }
      

  3.   

    这个程序能够正常编译,执行也没有问题,而且多个客户端连接的时候也能够相互聊天,但是有一个bug:在AppClient里面的线程里报connect reset异常,可能和套结字有关,如何解决,不胜感激!
      

  4.   

    没人来,酸了,结贴了.
    其实程序没有问题,只不过是socket的一个缺陷啊!