聊天室系统的开发在上面小张对在开发中要用到的开发工具给开发组成员做了详细的介绍,还有一些小程序的测试与说明,这样让公司的人对Java语言有了一定的了解,下面就是公司的开发项目聊天室程序的开发过程,在这个过程中他对代码也做了详细的注释。 聊天室系统效果图如图4-1所示: 图4-1聊天室系统界面 4.1 需求分析 4.1.1 设计目标 1、项目说明 项目名称:JAVA聊天室系统。 客户:一般大众。 2、项目背景 聊天室是网络社区中最主要的表现形式之一,在网络营销中有着独到的应用。网络社区可以增进和访问者或客户之间的关系,也可能直接...
Description: The multithread server and the server for one client.
*Copyright: Copyright (c) 2005
*Company:
* @author kentty * @version 1.0 */ public class MultiJabberServer extends Thread { public static final int PORT = 5555; //The PORT of chat service,you can change this number. public String []user; //To store the users public static int num; //The total useres ServerSocket ss; //ServerSocket TotalClient client; //the client /** * The constructer. * @throws IOException */ public MultiJabberServer() throws IOException { user = new String[100]; client = new TotalClient(); ss = new ServerSocket(PORT); } /** * The thread running method. * @return void */ public void run() { JOptionPane.showMessageDialog(new JWindow(),"服务器已启动!"+ss,"系统消息",JOptionPane.INFORMATION_MESSAGE); System.out.println("Server started:" + ss); try { while (true) { Socket s = ss.accept();//While one client connected the server return one socket. client.add(s); //add the client to totalclient. client.elementCount++; client.currentclient++; ServeoneJabber soj = new ServeoneJabber(s, client,user,num++); //Start the serveronejabber to serve the client. System.out.println("Connection accepted:" + s); } } catch (IOException ioe) { ioe.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } 通过初始化,先生成ServerSocket: ss = new ServerSocket(PORT); 当启动多线程服务器后,服务器就处于监听状态。 Socket s = ss.accept(); 当一个客户端进行连接后,服务器端便返回一个Socket,我们就可以利用这个Socket去找到任一对应的客户端,进行后面的发送消息等操作。 /** * Send system message to the total client. * @param mess String * @throws IOException * @return String the status of the result. * @author kentty * @version 1.0 */ public String castMessage(String mess) throws IOException { boolean isSend=false; int i; for (i = 0; i < client.elementCount; i++) { Socket sss = (Socket)client.elementAt(i); System.out.println(sss); PrintWriter everyout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(sss.getOutputStream())),true); everyout.println(">>>>系统广播: "+mess); System.out.println("Send ok!"); } if (i == client.elementCount+1) { isSend = true; } if (isSend==true) { return (mess); } return ""; } } //========================程序结束===========================// 4.3.2 服务器主界面 下面是服务器主界面程序分析: 设计思想: StartServer类继承自Jframe类,提供操作界面,并实现ActionListener接口,进行事件侦听。 (1)界面设计,提供“启动服务器”、“关闭服务器”、“启动客户端”、“关闭客户端”、“发送系统广播”按扭,显示服务器状态信息的状态栏,提供“系统消息”文本框。 (2)当点击“启动服务器”后,启动一个MultiJabberServer对象,并进行端口侦听。 (3)发送系统广播,向每一个客户端发送消息。 (4)在信息提示栏显示相应的提示信息。 //============================程序开始===========================// //DBC StartServer.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; public class StartServer extends JFrame implements ActionListener { JFrame menuj; JFrame totaluserj; JFrame contentj; JButton startserver; JButton stopserver; JButton startclient; JButton stopclient; JTextField state; JTextArea messagearea; JScrollPane textAreaScrollPane; // JTextArea totaluser; JLabel tishi; JTextField content; JButton send; MultiJabberServer mjs; public StartServer() { menuj = new JFrame(); totaluserj = new JFrame(); contentj = new JFrame(); startserver = new JButton("启动服务器"); stopserver = new JButton("关闭服务器"); startclient = new JButton("启动客户端"); stopclient = new JButton("关闭客户端"); state = new JTextField(15); state.setEditable(false); // totaluser = new JTextArea(); tishi = new JLabel("系统广播:"); content = new JTextField(20); send = new JButton("发送"); messagearea = new JTextArea(); messagearea.setEditable(false); textAreaScrollPane = new JScrollPane(messagearea); menuj.getContentPane().setLayout(new FlowLayout()); menuj.getContentPane().add(startserver); menuj.getContentPane().add(stopserver); menuj.getContentPane().add(startclient); menuj.getContentPane().add(stopclient); menuj.getContentPane().add(state); totaluserj.getContentPane().setLayout(new BorderLayout()); totaluserj.getContentPane().add(textAreaScrollPane,BorderLayout.CENTER); contentj.getContentPane().setLayout(new BorderLayout()); contentj.getContentPane().add(tishi,BorderLayout.WEST); contentj.getContentPane().add(content,BorderLayout.CENTER); contentj.getContentPane().add(send,BorderLayout.EAST); this.getContentPane().setLayout(new BorderLayout()); this.getContentPane().add(menuj.getContentPane(),BorderLayout.NORTH); this.getContentPane().add(totaluserj.getContentPane(),BorderLayout.CENTER); this.getContentPane().add(contentj.getContentPane(),BorderLayout.SOUTH); startserver.addActionListener(this); stopserver.addActionListener(this); startclient.addActionListener(this); stopclient.addActionListener(this); content.addActionListener(this); send.addActionListener(this); } public static void main(String[] args) { StartServer ss = new StartServer(); try { ss.mjs = new MultiJabberServer(); }catch(IOException ioe) { ss.showState("can't"); } ss.setSize(600,400); ss.setVisible(true); ss.setResizable(false); ss.setDefaultCloseOperation(EXIT_ON_CLOSE); ss.setTitle("^_^ 欢迎使用JAVA爱好者BBS系统『服务器』"); }// public void showState(String states) { if (states.equals("start")) { state.setText("服务器已启动..."); } else if (states.equals("stop")) { state.setText("服务器已关闭!"); } else if(states.equals("can't")) { state.setText("不能启动服务线程!"); } else state.setText(states); } public void actionPerformed(ActionEvent e) { if(e.getSource()==content||e.getSource()==send) { String mess= content.getText(); content.setText(""); try { String messstr=this.mjs.castMessage(mess); messagearea.append("系统消息已发送: "+mess+"\n"); }catch(IOException ioe) { showState("不能发送消息!"); } } else if (e.getSource()==startserver) { this.mjs.start(); //启动服务器 showState("start"); } else if(e.getSource()==stopserver) { this.mjs.stop(); showState("stop"); } else if(e.getSource()==startclient) { String [] args=new String[5]; new LoginFrame().main(args); } else if(e.getSource()==stopclient) { } } } //============================程序结束=========================// 4.3.3 登陆界面 设计思想: (1)提供用户登陆界面,用户信息输入、连接服务器等功能。 (2)常用用户信息正确性验证。 (3)登陆成功后,生成一个客户端的主界面对象,由该对象生成一个客户端对象。 //==========================程序开始=========================// //DBC LoginFrame.class import java.awt.*; import java.awt.event.*; import javax.swing.*; public class LoginFrame extends JFrame implements ActionListener { private JPanel center; private Container mainc; private String username; private String passwords; private int pp; JTextField u; JTextField p; JTextField s; JTextField serverport; JLabel selectserver; JLabel port; JLabel user; JLabel pass; JButton ok; JButton cancle; public LoginFrame() { selectserver = new JLabel("服务器:"); port = new JLabel("端 口:"); user = new JLabel("用户名:"); pass = new JLabel("密 码:"); ok = new JButton("确定"); cancle = new JButton("取消"); u = new JTextField("LGT",12); p = new JTextField("None",12); s = new JTextField("ServerName",12); serverport = new JTextField("5555",12); mainc = this.getContentPane(); mainc.setLayout(new FlowLayout()); ok.addActionListener(this); cancle.addActionListener(this); u.addActionListener(this); p.addActionListener(this); s.addActionListener(this); serverport.addActionListener(this); mainc.add(selectserver); mainc.add(s); mainc.add(port); mainc.add(serverport); mainc.add(user); mainc.add(u); mainc.add (pass); mainc.add(p); mainc.add(ok); mainc.add(cancle); } public static void main(String[] args) { LoginFrame log = new LoginFrame(); log.setSize(250,180); log.setVisible(true); log.setDefaultCloseOperation(EXIT_ON_CLOSE); log.setResizable(false); log.setTitle("JAVA.BBS.登陆"); } public void actionPerformed(ActionEvent e) { if (e.getSource()==ok||e.getSource()==u||e.getSource()==p||e.getSource()==s||e.getSource()==serverport) { username = this.u.getText(); passwords = this.p.getText(); if (serverport.getText().equals("")) { pp = 5555; } else pp = Integer.parseInt(this.serverport.getText()); if (username.equals("")) { JOptionPane.showMessageDialog(this,"请输入用户名!","信息提示",JOptionPane.ERROR_MESSAGE); return ; } if(this.checkPass(passwords).equals(new Boolean(true))); { MainBord mb = new MainBord(600,400,"JAVA爱好者聊天室 当前用户: "+username,username,s.getText(),pp); Thread t1 = new Thread(mb); t1.start(); mb.setVisible(true); mb.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(false); } } else if (e.getSource()==cancle) { this.dispose(); } } public Boolean checkPass(String pass) { return new Boolean(true); } } //==========================程序结束============================// 4.3.4 客户端对象 设计思想: (1)先总体设计该类,将该类封装为一个客户端,向用户提供连接服务器、接收消息、发送消息等功能。 (2)在连接上服务器后,会创建该类的一个实例,代表一个客户端。利用该客户端进行所有的客户活动。 (3)提供receiveMessage()、sendMessage(Stringmsg)方法,进行接收消息和发送消息。同时在发送消息时进行一些错误控制如不能发送空消息等。 //=============================程序开始=========================// //DBC Client.java import java.io.*; import java.net.*; import javax.swing.*; class Client { private static int PORT=5555; private Socket s; private BufferedReader in; private PrintWriter out; private String username; private String servername; private int port; JTextArea jTextArea1 = new JTextArea(); JButton jButton1 = new JButton(); public Client(String name,String servername,int port) { username = name; this.servername = servername; this.port = port; try { InetAddress addr = InetAddress.getByName(servername); s = new Socket(addr,port); JOptionPane.showMessageDialog(new JWindow(),"已连接服务器!"+s,"连接成功",JOptionPane.INFORMATION_MESSAGE); in = new BufferedReader(new InputStreamReader(s.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter( s. getOutputStream())), true); out.println(username); System.out.println(username); }catch (UnknownHostException ue) { JOptionPane.showMessageDialog(new JWindow(),"出现错误:未知主机..."+ue.getMessage(),"聊天错误",JOptionPane.ERROR_MESSAGE); }catch (NullPointerException npe){ JOptionPane.showMessageDialog(new JWindow(),"出现错误:服务器未开启..."+npe.getMessage(),"连接错误",JOptionPane.ERROR_MESSAGE); }catch (IOException e) { } } public String receiveMessage() throws Throwable { try { while (true) { if (s.isClosed()) { throw(new Throwable()); } String str=""; str =in.readLine(); return str; } }catch(IOException e) { System.out.println("读取数据错误..."); throw(new Throwable()); }catch(Throwable t){ throw(new Throwable()); } } public void sendMessage(String str) { if (str.equals("")) { JOptionPane.showMessageDialog(new JWindow(),"不能发送空消息!","聊天提示", JOptionPane.ERROR_MESSAGE); return; } out.println(username+" 说: "+str); } public Client() { try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } private void jbInit() throws Exception { jButton1.setText("jButton1"); jTextArea1.setText("jTextArea1"); } } //==============================程序结束=========================// 4.3.5 聊天室主界面 设计思想: (1)用户登陆成功后的主操作界面,提供聊天信息发送、聊天信息显示、显示在线用户、退出、重登陆、隐身等功能(注意,某些功能未实现,读者可以在此基础上添加)。 (2)在该类主要封闭了聊天信息的具体显示、在线用户的刷新等功能的实现。 (3)注意该线程实现了Runnable接口,提供多线程服务。 //===========================程序开始==========================// //DBC MainBord.java文件 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class MainBord extends JFrame implements ActionListener,Runnable { private static JLabel[] totalu; private static int num; private String username; private String servername; private int width,height; private String title; JFrame top; JFrame bottom; JFrame menu; JFrame user; Container topc; Container menuc; Container bottomc; Container c; Container u; JTextArea messagearea; JTextArea userarea; JScrollPane textAreaScrollPane; JLabel tishi; JTextField mess; JButton send; JButton ying; JButton cancle; JButton login; JButton reg; Client client; MultiJabberServer server; public MainBord(int width,int height,String title,String name,String servername,int port) { totalu = new JLabel[100]; num = 0; username = name; this.servername = servername; this.width = width; this.height = height; this.title = title; top = new JFrame(); bottom = new JFrame(); menu = new JFrame(); user =new JFrame(); topc = top.getContentPane(); bottomc = bottom.getContentPane(); menuc = menu.getContentPane(); c = this.getContentPane(); u = user.getContentPane(); topc.setLayout(new BorderLayout()); bottomc.setLayout(new BorderLayout()); menuc.setLayout(new GridLayout()); c.setLayout(new BorderLayout()); u.setLayout(new BorderLayout()); tishi = new JLabel("消息:"); mess = new JTextField(); send = new JButton("发送"); messagearea = new JTextArea(); messagearea.setEditable(false); textAreaScrollPane = new JScrollPane(messagearea); ying = new JButton("隐身"); cancle = new JButton("退出"); login = new JButton("登陆"); reg = new JButton("注册"); userarea = new JTextArea(10,10); userarea.setBackground(new Color(180,180,180)); userarea.setForeground(new Color(150,180,150)); userarea.setLayout(new GridLayout(20,1)); client = new Client(username,servername,port); menuc.add(ying); menuc.add(cancle); menuc.add(login); menuc.add(reg); topc.add(textAreaScrollPane,BorderLayout.CENTER); topc.add(menuc,BorderLayout.NORTH); bottomc.add(tishi,BorderLayout.WEST); bottomc.add(mess,BorderLayout.CENTER); bottomc.add(send,BorderLayout.EAST); u.add(new JButton("当前在线用户"),BorderLayout.NORTH); u.add(userarea,BorderLayout.CENTER); c.add(topc,BorderLayout.CENTER); c.add(bottomc,BorderLayout.SOUTH); //c.add(menuc,BorderLayout.NORTH); c.add(u,BorderLayout.EAST); setSize(width,height); this.setTitle(title); mess.addActionListener(this); send.addActionListener(this); cancle.addActionListener(this); this.setDefaultCloseOperation(EXIT_ON_CLOSE); } public void actionPerformed(ActionEvent e) { if((e.getSource()==mess)||(e.getSource()==send)) { String message=mess.getText(); mess.setText(""); try { client.sendMessage(message); } catch(Throwable ex) { JOptionPane.showMessageDialog(this,"信息发送出现错误:"+ex.getMessage(),"聊天错误",JOptionPane.ERROR_MESSAGE); } } else if(e.getSource()==cancle) { JOptionPane.showMessageDialog(this,"客户端将关闭!","[信息提示]", JOptionPane.CLOSED_OPTION); this.dispose(); } } public void run() { String mess; while(true) { try { mess = client.receiveMessage(); System.out.println(mess); if (mess.equals("refreshUsers")) { refreshUser(client.receiveMessage(),totalu,num); num++; } else messagearea.append(mess+"\n"); }catch(Throwable te){ JOptionPane.showMessageDialog(this,"服务器已关闭!","聊天错误", JOptionPane.ERROR_MESSAGE); break; } textAreaScrollPane.getVerticalScrollBar().setValue(textAreaScrollPane.getVerticalScrollBar().getMaximum()); } } public static void main(String [] args) { } public void refreshUser(String username, JLabel[] j,int k) { // for(int i = 0;i