Java聊天室附完整代码

xiao132

贡献于2015-05-29

字数:38006 关键词: 电话/通讯/IM聊天 Java

 专业课程设计I 基于JAVA的聊天室设计与实现 一、课题内容和要求 基于网络的文本交互软件的设计和实现,设计和实现一个简单的基于网络的文本消息发送和接收软件。基本要求:该软件能实现文本消息发送和接收功能。提高要求(1):支持以多播方式发送文本消息,提高要求(2):性能稳定,界面友好。按课程设计报告的要求写出详细的设计和实现报告。 二、设计思路分析 聊天室是一项进行文本交互的软件,应用广泛,并且实用性强的一个非常典型的人机交互系统。在信息世界里,聊天工具的使用是非常频繁的,如MSN、QQ、校内通之类的聊天工具许多人都正在使用。此次设计的聊天室系统主要针对文本信息的传送和接收,不能像QQ一样进行图片、音频、视频等文件的传输。虽然其功能简单,但是在开发技术和过程中,能够充分学习和使用JAVA的技术,进一步培养了面向对象程序设计的思想,加深对面向对象程序设计四大特性的理解。 人们日常生活中越来越多地使用聊天室这项应用来为自己的工作和学习服务。一个操作简单,界面友好、运行稳定的聊天室对于小型局域网的用户可以起到很好的交流作用。所谓聊天室就是一个可以让许多用户同时互相通信的网上园地,个人用户可以通过聊天室将自己融入整个主流社会中。 根据目前使用聊天室的用户需求显示,用户对于聊天室主要有以下几点要求: (1)聊天功能:可以实时接收和发送信息,并能支持公聊和私聊的的方式,能够查看聊天记录,聊天过程中能对字体、表情等进行设定等。 (2)用户功能:可以随时注册和登录及注销,并能选择性加好友和删除好友以及查看对方的开放信息,还能看到对方的登录状态。 (3)文件传输功能:用户可以共享资源,能发送及接收文件。 (4)保密功能:用户可以设定自己的保密状态,使某些信息对于其他用户是不可见的。 (5)系统稳定:客户端与服务端的连接稳定,不出现或者少出现连接不上的情况。 三、概要设计 1、聊天室的简要功能介绍 该简易聊天室是为许多喜爱聊天的用户开发设计的,和许多大型的网络聊天室相比该小聊天室功能比较简单,但能实现基本的聊天功能,点对多、点对点聊天和基本的用户功能,登录、注销、查看在线用户等。 (1) 用户设置: 功能描述:用户自定义自己的登录名,成功设置后,服务端能接收到新设置的用户名; (2) 登录功能: 功能描述:在服务端开启的情况下,用户可以以自己自定义或者默认的登录名和登录地址端口登录到客户端,并能在服务器端显示登录状态; (3) 公聊: 功能描述:用户在聊天室中可以选择与“所有人”聊天,聊天室中的其他在线用户可以正常接收并正确显示公聊消息。 (4) 私聊: 功能描述:用户可以选择与聊天室的在线用户列表中的其他用户聊天。双方的聊天记录对于聊天室的其他用户是不可见的。 (5) 聊天心情: 功能描述:用户在聊天的过程中可以选择相应的心情来表达自己的情感。 (6) 系统消息: 功能描述:服务端正常运行的过程中,在聊天室的每一个用户都能接收服务器端发送的信息提示信息。 (7) 用户的状态. 功能描述:每一个客户端用户都可以实时看到目前其他在线用户的状态。 (8) 用户注销: 功能描述:用户可以注销自己的账号,并重新登记登录名和地址。 (9) 用户退出: 功能描述:用户可以在正常情况下退出聊天室。 (10) 服务端控制: 功能描述:只有在服务端开启的情况下,用户才能登陆成功和聊天;用户设置的地址端口也必须与服务端的侦听端口一致,否则不能登录。 2、模块描述 本聊天室分为聊天室服务端和聊天室客户端,服务端与客户端之间通过套接口Socket(TCP)连接。在java中使用套接口相当简单,Java API为处理套接口的通信提供了一个类java.net.Socket.,使得编写网络应用程序相对容易.服务器采用多线程以满足多用户的请求,通过JDBC与后台数据库连接,并通过创建一个ServerSocket对象来监听来自客户的连接请求,默认IP地址为:127.0.0.1默认端口为8888。 (1) 聊天室服务端模块图: 聊天室服务端 端口服务 启动服务 发送系统消息 停止服务 退出 服务器 消息显示 端口服务:输入要侦听的端口,默认为8888; 启动服务:启动服务器,并开始在设置的端口中侦听,客户端用户可以登录并开始聊天; 停止服务:关闭服务器,侦听结束。客户端用户不能再聊天; 发送系统消息:服务器端给所有人或者个别用户发送消息。 消息显示:可以显示所有用户的聊天记录,和上线、下线信息。 退出服务器:退出程序,并停止服务; (2)聊天室客户端模块图: 聊天室客户端 连接设置 用户登录 退 出 发 送 接收聊天消 息 用户注销 用户设置 用户设置:用户可以设置自己的用户名进行聊天; 连接设置:用户可以设置自己的服务器的IP地址和端口号,默认的连接地址为:127.0.0.1:8888; 用户登录:只能在聊天室服务端已开启的情况下,用户才能登录,用户登录之后才能开始聊天,登录后不能再修改用户设置和连接设置; 用户注销:退出聊天,可以继续修改用户设置和连接设置; 发送和接收聊天信息:用户可以给所有人或者个别用户发送信息,并能看到其他用户发送给自己或所有人的消息; 退出:关闭所有聊天并退出客户端。 (3) 流程图 聊天室服务器 端口服务 启动服务 聊天室客户端 登录 连接设置 聊天 退出 默认连接地址或用户名 设置侦听端口 默认端口:8888 用户设置 设置用户名 设置IP地址和端口 四、详细设计 ActionListener ChatServer -port:public static in -serverSocket:ServerSocket -messageShow:JTextArea -userLinkList:UserLinkList -showStatus:JTextField + ChatServer():public +init():public void +startService():public void +stopService():public void +sendStopToAll():public void +sendMsgToAll(String):public void + sendSystemMessage():public void JFrame Thread ServerListen - server: ServerSocket - userLinkList :UserLinkList - isStop: public Boolean +ServerListen(ServerSocket,JComboBox,JTextArea,JTextField,UserLinkList) ServerReceive -textarea:JTextArea - userLinkList :UserLinkList - isStop: public Boolean +ServerListen(ServerSocket,JComboBox,JTextArea,JTextField,UserLinkList) 1、聊天室服务器端设计: ServerListen - server: ServerSocket - userLinkList :UserLinkList - isStop: public Boolean +ServerListen(ServerSocket,JComboBox,JTextArea,JTextField,UserLinkList) 聊天室服务端主要包括7个文件,它们的功能如下: (1)ChatServer.java:包含名为ChatServer的public类,其主要功能为定义服务器端的界面,添加事件侦听与事件处理。调用ServerListen类来实现服务端用户上线与下线的侦听,调用ServerReceive类来实现服务器端的消息的收发。 (2)ServerListen.java:该类实现服务端用户上线与下线的侦听。该类对用户上线下线的侦听是通过调用用户链表类(UserLinkList)来实现的,当用户上线与下线情况发生变化时,该类会对主类的界面进行相应的修改。 (3)ServerReceive.java:该类是实现服务器端的消息的收发的类。该类分别定义了向某用户及所有人发送消息的方法,发送的消息会显示在主界面类的界面上。 (4)PortConf.java:该类继承自JDialog,是用户对服务器端侦听端口进行修改配置的类。 (5)Node.java:用户链表的节点类,定义了链表中的用户。该类与前面所讲的链表节点Node类的功能相当。 (6)UserLinkList.java:用户链表节点的具体实现类。该类通过构造函数构造用户链表,定义了添加用户,删除用户、返回用户数、根据用户名查找用户、根据索引查找用户这5个方法。 (7)Help.java:服务端程序的帮助类。 2、聊天室客户端设计: ActionListener ChatClient -port:public static in -serverSocket:ServerSocket -messageShow:JTextArea -userLinkList:UserLinkList -showStatus:JTextField + ChatClient():public +init():public void +Connect():public void +DisConnect():public void +SendMessage():public void JFrame Thread ClientReceive - socket: Socket -output:ObjectOutputStream -input:ObjectInputStream +ClientReceive(Socket,ObjectOutputStream,ObjectInputStream,JComboBox,JTextArea,JTextField ) 聊天室客户端主要包括5个文件,它们的功能如下: (1)ChatClient.java:包含名为ChatClient的public类,其主要功能为定义客户端的界面,添加事件侦听与事件处理。该类定义了Connect()与DisConnect()方法实现与服务器的连接与断开连接。当登录到指定的服务器时,调用ClientReceive类实现消息收发,同时该类还定义了SendMessage()方法来向其他用户发送带有表情的消息或者悄悄话。 (2)ClientReceive.java:该类是实现服务器端与客户端消息收发的类。 (3)ConnectConf.java:该类继承自JDialog,是用户对所要连接的服务器IP及侦听端口进行修改配置的类。 (4)UserConf.java:该类继承自JDialog,是用户对连接到服务器所显示的用户名进行修改配置的类。 (5)Help.java:客户端程序的帮助类。 五、测试数据及其结果分析 1、首先运行ChatServer工程文件,会出现如下画面 2、选择端口设置,可以设置您要侦听的端口号,不设置将默认端口号为8888; 3、选择启动服务,服务器开始在您刚才设置的端口中侦听; 4、运行ChatClient工程文件,打开如下画面 5、选择用户设置可以设置自己的登录名 6、选择连接设置可以设置您的IP地址和端口号 7、选择登录进入聊天室并可以开始跟所有人或者个别其他用户聊天,其中可以选择心情等; 8、在服务端也可以选择给所有人或者个别用户发送消息; 注意:客户端只有在服务端开启的情况下才能正常聊天。 9、多人聊天的服务器端与客户端情况 代码如下: package liaotian; /** * 用户链表 */ public class UserLinkList { Node root; Node pointer; int count; /** * 构造用户链表 */ public UserLinkList(){ root = new Node(); root.next = null; pointer = null; count = 0; } /** * 添加用户 */ public void addUser(Node n){ pointer = root; while(pointer.next != null){ pointer = pointer.next; } pointer.next = n; n.next = null; count++; } /** * 删除用户 */ public void delUser(Node n){ pointer = root; while(pointer.next != null){ if(pointer.next == n){ pointer.next = n.next; count --; break; } pointer = pointer.next; } } /** * 返回用户数 */ public int getCount(){ return count; } /** * 根据用户名查找用户 */ public Node findUser(String username){ if(count == 0) return null; pointer = root; while(pointer.next != null){ pointer = pointer.next; if(pointer.username.equalsIgnoreCase(username)){ return pointer; } } return null; } /** * 根据索引查找用户 */ public Node findUser(int index){ if(count == 0) { return null; } if(index < 0) { return null; } pointer = root; int i = 0; while(i < index + 1){ if(pointer.next != null){ pointer = pointer.next; } else{ return null; } i++; } return pointer; } } package liaotian; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import javax.swing.*; /* * 聊天客户端的主框架类 */ public class ChatClient extends JFrame implements ActionListener{ /** * */ private static final long serialVersionUID = 1L; String ip = "127.0.0.1";//连接到服务端的ip地址 int port = 8888;//连接到服务端的端口号 String userName = "狂狂";//用户名 int type = 0;//0表示未连接,1表示已连接 JComboBox combobox;//选择发送消息的接受者 JTextArea messageShow;//客户端的信息显示 JScrollPane messageScrollPane;//信息显示的滚动条 JLabel express,sendToLabel,messageLabel ; JTextField clientMessage;//客户端消息的发送 JCheckBox checkbox;//悄悄话 JComboBox actionlist;//表情选择 JButton clientMessageButton;//发送消息 JTextField showStatus;//显示用户连接状态 Socket socket; ObjectOutputStream output;//网络套接字输出流 ObjectInputStream input;//网络套接字输入流 ClientReceive recvThread; //建立菜单栏 JMenuBar jMenuBar = new JMenuBar(); //建立菜单组 JMenu operateMenu = new JMenu ("操作(O)"); //建立菜单项 JMenuItem loginItem = new JMenuItem ("用户登录(I)",new ImageIcon("face/98.gif")); JMenuItem logoffItem = new JMenuItem ("用户注销(L)",new ImageIcon("face/icon.gif")); JMenuItem exitItem=new JMenuItem ("退出(X)",new ImageIcon("face/smile.gif")); JMenu conMenu=new JMenu ("设置(C)"); JMenuItem userItem=new JMenuItem ("用户设置(U)",new ImageIcon("face/messenger_big.gif")); JMenuItem connectItem=new JMenuItem ("连接设置(C)",new ImageIcon("face/Uabrand.gif")); JMenu helpMenu=new JMenu ("帮助(H)"); JMenuItem helpItem=new JMenuItem ("帮助(H)",new ImageIcon("face/HelpCenter.gif")); //建立工具栏 JToolBar toolBar = new JToolBar(); //建立工具栏中的按钮组件 JButton loginButton;//用户登录 JButton logoffButton;//用户注销 JButton userButton;//用户信息的设置 JButton connectButton;//连接设置 JButton exitButton;//退出按钮 //框架的大小 Dimension faceSize = new Dimension(400, 600); JPanel downPanel ; GridBagLayout girdBag; GridBagConstraints girdBagCon; public ChatClient(){ init();//初始化程序 //添加框架的关闭事件处理 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.pack(); //设置框架的大小 this.setSize(faceSize); this.setVisible(true); setIconImage(getToolkit().getImage("face/love.gif")); //设置运行时窗口的位置 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation( (int) (screenSize.width - faceSize.getWidth()) / 2, (int) (screenSize.height - faceSize.getHeight()) / 2); this.setResizable(false); this.setTitle("聊天室客户端"); //设置标题 //为操作菜单栏设置热键'V' operateMenu.setMnemonic('O'); //为用户登录设置快捷键为ctrl+i loginItem.setMnemonic ('I'); loginItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_I,InputEvent.CTRL_MASK)); //为用户注销快捷键为ctrl+l logoffItem.setMnemonic ('L'); logoffItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_L,InputEvent.CTRL_MASK)); //为退出快捷键为ctrl+x exitItem.setMnemonic ('X'); exitItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_X,InputEvent.CTRL_MASK)); //为设置菜单栏设置热键'C' conMenu.setMnemonic('C'); //为用户设置设置快捷键为ctrl+u userItem.setMnemonic ('U'); userItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_U,InputEvent.CTRL_MASK)); //为连接设置设置快捷键为ctrl+c connectItem.setMnemonic ('C'); connectItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_C,InputEvent.CTRL_MASK)); //为帮助菜单栏设置热键'H' helpMenu.setMnemonic('H'); //为帮助设置快捷键为ctrl+p helpItem.setMnemonic ('H'); helpItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_H,InputEvent.CTRL_MASK)); } /** * 程序初始化函数 */ public void init(){ Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); //添加菜单栏 operateMenu.add (loginItem); operateMenu.add (logoffItem); operateMenu.addSeparator(); operateMenu.add (exitItem); jMenuBar.add (operateMenu); conMenu.add (userItem); conMenu.addSeparator(); conMenu.add (connectItem); jMenuBar.add (conMenu); helpMenu.add (helpItem); jMenuBar.add (helpMenu); setJMenuBar (jMenuBar); //初始化按钮 loginButton = new JButton("登录"); logoffButton = new JButton("注销"); userButton = new JButton("用户设置" ); connectButton = new JButton("连接设置" ); exitButton = new JButton("退出" ); //当鼠标放上显示信息 loginButton.setToolTipText("连接到指定的服务器"); logoffButton.setToolTipText("与服务器断开连接"); userButton.setToolTipText("设置用户信息"); connectButton.setToolTipText("设置所要连接到的服务器信息"); //将按钮添加到工具栏 toolBar.add(userButton); toolBar.add(connectButton); toolBar.addSeparator();//添加分隔栏 toolBar.add(loginButton); toolBar.add(logoffButton); toolBar.addSeparator();//添加分隔栏 toolBar.add(exitButton); contentPane.add(toolBar,BorderLayout.NORTH); checkbox = new JCheckBox("悄悄话"); checkbox.setSelected(false); actionlist = new JComboBox(); actionlist.addItem("微笑地"); actionlist.addItem("高兴地"); actionlist.addItem("轻轻地"); actionlist.addItem("生气地"); actionlist.setSelectedIndex(0); //初始时 loginButton.setEnabled(true); logoffButton.setEnabled(false); //为菜单栏添加事件监听 loginItem.addActionListener(this); logoffItem.addActionListener(this); exitItem.addActionListener(this); userItem.addActionListener(this); connectItem.addActionListener(this); helpItem.addActionListener(this); //添加按钮的事件侦听 loginButton.addActionListener(this); logoffButton.addActionListener(this); userButton.addActionListener(this); connectButton.addActionListener(this); exitButton.addActionListener(this); combobox = new JComboBox(); combobox.insertItemAt("所有人",0); combobox.setSelectedIndex(0); messageShow = new JTextArea(); messageShow.setEditable(false); //添加滚动条 messageScrollPane = new JScrollPane(messageShow, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); messageScrollPane.setPreferredSize(new Dimension(400,400)); messageScrollPane.revalidate(); clientMessage = new JTextField(23); clientMessage.setEnabled(false); clientMessageButton = new JButton(); clientMessageButton.setText("发送"); //添加系统消息的事件侦听 clientMessage.addActionListener(this); clientMessageButton.addActionListener(this); sendToLabel = new JLabel("发送至:"); express = new JLabel(" 表情: "); messageLabel = new JLabel("发送消息:"); downPanel = new JPanel(); girdBag = new GridBagLayout(); downPanel.setLayout(girdBag); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 0; girdBagCon.gridy = 0; girdBagCon.gridwidth = 5; girdBagCon.gridheight = 2; girdBagCon.ipadx = 5; girdBagCon.ipady = 5; JLabel none = new JLabel(" "); girdBag.setConstraints(none,girdBagCon); downPanel.add(none); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 0; girdBagCon.gridy = 2; girdBagCon.insets = new Insets(1,0,0,0); //girdBagCon.ipadx = 5; //girdBagCon.ipady = 5; girdBag.setConstraints(sendToLabel,girdBagCon); downPanel.add(sendToLabel); girdBagCon = new GridBagConstraints(); girdBagCon.gridx =1; girdBagCon.gridy = 2; girdBagCon.anchor = GridBagConstraints.LINE_START; girdBag.setConstraints(combobox,girdBagCon); downPanel.add(combobox); girdBagCon = new GridBagConstraints(); girdBagCon.gridx =2; girdBagCon.gridy = 2; girdBagCon.anchor = GridBagConstraints.LINE_END; girdBag.setConstraints(express,girdBagCon); downPanel.add(express); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 3; girdBagCon.gridy = 2; girdBagCon.anchor = GridBagConstraints.LINE_START; //girdBagCon.insets = new Insets(1,0,0,0); //girdBagCon.ipadx = 5; //girdBagCon.ipady = 5; girdBag.setConstraints(actionlist,girdBagCon); downPanel.add(actionlist); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 4; girdBagCon.gridy = 2; girdBagCon.insets = new Insets(1,0,0,0); //girdBagCon.ipadx = 5; //girdBagCon.ipady = 5; girdBag.setConstraints(checkbox,girdBagCon); downPanel.add(checkbox); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 0; girdBagCon.gridy = 3; girdBag.setConstraints(messageLabel,girdBagCon); downPanel.add(messageLabel); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 1; girdBagCon.gridy = 3; girdBagCon.gridwidth = 3; girdBagCon.gridheight = 1; girdBag.setConstraints(clientMessage,girdBagCon); downPanel.add(clientMessage); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 4; girdBagCon.gridy = 3; girdBag.setConstraints(clientMessageButton,girdBagCon); downPanel.add(clientMessageButton); showStatus = new JTextField(35); showStatus.setEditable(false); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 0; girdBagCon.gridy = 5; girdBagCon.gridwidth = 5; girdBag.setConstraints(showStatus,girdBagCon); downPanel.add(showStatus); contentPane.add(messageScrollPane,BorderLayout.CENTER); contentPane.add(downPanel,BorderLayout.SOUTH); //关闭程序时的操作 this.addWindowListener( new WindowAdapter(){ public void windowClosing(WindowEvent e){ if(type == 1){ DisConnect(); } System.exit(0); } }); } /** * 事件处理 */ public void actionPerformed(ActionEvent e) { Object obj = e.getSource(); if (obj == userItem || obj == userButton) { //用户信息设置 //调出用户信息设置对话框 UserConf userConf = new UserConf(this,userName); userConf.setVisible(true); userName = userConf.userInputName; } else if (obj == connectItem || obj == connectButton) { //连接服务端设置 //调出连接设置对话框 ConnectConf conConf = new ConnectConf(this,ip,port); conConf.setVisible(true); ip = conConf.userInputIp; port = conConf.userInputPort; } else if (obj == loginItem || obj == loginButton) { //登录 Connect(); } else if (obj == logoffItem || obj == logoffButton) { //注销 DisConnect(); showStatus.setText(""); } else if (obj == clientMessage || obj == clientMessageButton) { //发送消息 SendMessage(); clientMessage.setText(""); } else if (obj == exitButton || obj == exitItem) { //退出 int j=JOptionPane.showConfirmDialog( this,"真的要退出吗?","退出", JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE); if (j == JOptionPane.YES_OPTION){ if(type == 1){ DisConnect(); } System.exit(0); } } else if (obj == helpItem) { //菜单栏中的帮助 //调出帮助对话框 Help helpDialog = new Help(this); helpDialog.setVisible(true); } } public void Connect(){ try{ socket = new Socket(ip,port); } catch (Exception e){ JOptionPane.showConfirmDialog( this,"不能连接到指定的服务器。\n请确认连接设置是否正确。","提示", JOptionPane.DEFAULT_OPTION,JOptionPane.WARNING_MESSAGE); return; } try{ output = new ObjectOutputStream(socket.getOutputStream()); output.flush(); input = new ObjectInputStream(socket.getInputStream() ); output.writeObject(userName); output.flush(); recvThread = new ClientReceive(socket,output,input,combobox,messageShow,showStatus); recvThread.start(); loginButton.setEnabled(false); loginItem.setEnabled(false); userButton.setEnabled(false); userItem.setEnabled(false); connectButton.setEnabled(false); connectItem.setEnabled(false); logoffButton.setEnabled(true); logoffItem.setEnabled(true); clientMessage.setEnabled(true); messageShow.append("连接服务器 "+ip+":"+port+" 成功...\n"); type = 1;//标志位设为已连接 } catch (Exception e){ System.out.println(e); return; } } public void DisConnect(){ loginButton.setEnabled(true); loginItem.setEnabled(true); userButton.setEnabled(true); userItem.setEnabled(true); connectButton.setEnabled(true); connectItem.setEnabled(true); logoffButton.setEnabled(false); logoffItem.setEnabled(false); clientMessage.setEnabled(false); if(socket.isClosed()){ return ; } try{ output.writeObject("用户下线"); output.flush(); input.close(); output.close(); socket.close(); messageShow.append("已经与服务器断开连接...\n"); type = 0;//标志位设为未连接 } catch (Exception e){ // } } public void SendMessage(){ String toSomebody = combobox.getSelectedItem().toString(); String status = ""; if(checkbox.isSelected()){ status = "悄悄话"; } String action = actionlist.getSelectedItem().toString(); String message = clientMessage.getText(); if(socket.isClosed()){ return ; } try{ output.writeObject("聊天信息"); output.flush(); output.writeObject(toSomebody); output.flush(); output.writeObject(action); output.flush(); output.writeObject(action); output.flush(); output.writeObject(message); output.flush(); } catch (Exception e){ // } } public static void main(String[] args) { new ChatClient(); } } package liaotian; import java.awt.*; import java.awt.event.*; import java.net.*; import javax.swing.*; public class ChatServer extends JFrame implements ActionListener{ public static int port=8888;//·þÎñÆ÷ÕìÌý¶Ë¿Ú ServerSocket serverSocket;//·þÎñ¶ËSocket JComboBox combobox; JTextArea messageShow; JTextField showStatus; JScrollPane messageScrollPane; JLabel sendToLabel,messageLabel; JTextField sysMessage; JButton sysMessageButton; UserLinkList userLinkList; JMenuBar jMenuBar=new JMenuBar(); JMenu serviceMenu = new JMenu("·þÎñ"); JMenuItem portItem = new JMenuItem("¶Ë¿ÚÉèÖÃ"); JMenuItem startItem = new JMenuItem("Æô¶¯·þÎñ"); JMenuItem stopItem = new JMenuItem("Í£Ö¹·þÎñ"); JMenuItem exitItem = new JMenuItem("ÍË ³ö"); JMenu helpMenu = new JMenu("°ïÖú"); JMenuItem helpItem = new JMenuItem("°ïÖú"); JToolBar toolBar = new JToolBar(); JButton portSet; JButton startServer; JButton stopServer; JButton exitButton; //¿ò¼Ü´óС Dimension faceSize = new Dimension(400,600); ServerListen listenThread; JPanel downPanel; GridBagLayout girdBag; GridBagConstraints girdBagCon; /** * ·þÎñ¶Ë¹¹Ô캯Êý */ public ChatServer(){ init();//³õʼ»¯³ÌÐò this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.pack(); this.setSize(faceSize); this.setVisible(true); //ÉèÖÃÔËÐÐʱ´°¿ÚλÖà Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation((int)(screenSize.width-faceSize.getWidth())/2, (int)(screenSize.height-faceSize.getHeight())/2); this.setResizable(false); this.setTitle("ÁÄÌìÊÒ·þÎñ¶Ë"); } public void init(){ Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); serviceMenu.add(portItem); serviceMenu.add(startItem); serviceMenu.addSeparator(); serviceMenu.add(stopItem); serviceMenu.addSeparator(); serviceMenu.add(exitItem); jMenuBar.add(serviceMenu); helpMenu.add(helpItem); jMenuBar.add(helpMenu); setJMenuBar(jMenuBar); //³õʼ»¯°´Å¥ portSet = new JButton("¶Ë¿ÚÉèÖÃ"); startServer = new JButton("Æô¶¯·þÎñ"); stopServer = new JButton("Í£Ö¹·þÎñ"); exitButton= new JButton("Í˳ö"); toolBar.add(portSet); toolBar.addSeparator(); toolBar.add(startServer); toolBar.add(stopServer); toolBar.addSeparator(); toolBar.add(exitButton); contentPane.add(toolBar,BorderLayout.NORTH); stopServer.setEnabled(false); stopItem.setEnabled(false); startItem.addActionListener(this); stopItem.addActionListener(this); portItem.addActionListener(this); exitItem.addActionListener(this); helpItem.addActionListener(this); portSet.addActionListener(this); startServer.addActionListener(this); stopServer.addActionListener(this); exitButton.addActionListener(this); combobox = new JComboBox(); combobox.insertItemAt("ËùÓÐÈË", 0); combobox.setSelectedIndex(0); messageShow = new JTextArea(); messageShow.setEditable(false); messageScrollPane = new JScrollPane(messageShow,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); messageScrollPane.setPreferredSize(faceSize); messageScrollPane.revalidate(); sysMessage = new JTextField(23); sysMessage.setEnabled(false); sysMessageButton = new JButton(); sysMessageButton.setText("·¢ËÍ"); sysMessage.addActionListener(this); sysMessageButton.addActionListener(this); sendToLabel = new JLabel("·¢ËÍÖÁ£º"); messageLabel = new JLabel("·¢ËÍÏûÏ¢"); downPanel = new JPanel(); girdBag=new GridBagLayout(); downPanel.setLayout(girdBag); girdBagCon = new GridBagConstraints(); girdBagCon.gridx=0; girdBagCon.gridy=0; girdBagCon.gridwidth=5; girdBagCon.gridheight=2; girdBagCon.ipadx=5; girdBagCon.ipady=5; JLabel none=new JLabel(" "); girdBag.setConstraints(none, girdBagCon); downPanel.add(none); girdBagCon = new GridBagConstraints(); girdBagCon.gridx=0; girdBagCon.gridy=2; girdBagCon.insets=new Insets(1,0,0,0); //girdBagCon.ipadx=5; //girdBagCon.ipady=5; girdBag.setConstraints(sendToLabel, girdBagCon); downPanel.add(sendToLabel); girdBagCon = new GridBagConstraints(); girdBagCon.gridx=1; girdBagCon.gridy=2; girdBagCon.anchor = GridBagConstraints.LINE_START; girdBag.setConstraints(combobox, girdBagCon); downPanel.add(combobox); girdBagCon = new GridBagConstraints(); girdBagCon.gridx=0; girdBagCon.gridy=3; girdBag.setConstraints(messageLabel, girdBagCon); downPanel.add(messageLabel); girdBagCon = new GridBagConstraints(); girdBagCon.gridx=1; girdBagCon.gridy=3; girdBagCon.gridwidth = 3; girdBagCon.gridheight = 1; girdBag.setConstraints(sysMessage, girdBagCon); downPanel.add(sysMessage); girdBagCon = new GridBagConstraints(); girdBagCon.gridx=4; girdBagCon.gridy=3; girdBag.setConstraints(sysMessageButton, girdBagCon); downPanel.add(sysMessageButton); showStatus = new JTextField(35); showStatus.setEditable(false); girdBagCon = new GridBagConstraints(); girdBagCon.gridx = 0; girdBagCon.gridy = 5; girdBagCon.gridwidth = 5; girdBag.setConstraints(showStatus,girdBagCon); downPanel.add(showStatus); contentPane.add(messageScrollPane,BorderLayout.CENTER); contentPane.add(downPanel,BorderLayout.SOUTH); this.addWindowListener( new WindowAdapter(){ public void windowClosing (WindowEvent e){ stopService(); System.exit(0); } } ); } /** * ʼþ´¦Àí */ @SuppressWarnings("deprecation") public void actionPerformed(ActionEvent e) { Object obj = e.getSource(); if (obj == startServer || obj == startItem) { //Æô¶¯·þÎñ¶Ë startService(); } else if (obj == stopServer || obj == stopItem) { //Í£Ö¹·þÎñ¶Ë int j=JOptionPane.showConfirmDialog( this,"ÕæµÄÍ£Ö¹·þÎñÂð?","Í£Ö¹·þÎñ", JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE); if (j == JOptionPane.YES_OPTION){ stopService(); } } else if (obj == portSet || obj == portItem) { //¶Ë¿ÚÉèÖà //µ÷³ö¶Ë¿ÚÉèÖõĶԻ°¿ò PortConf portConf = new PortConf(this); portConf.show(); } else if (obj == exitButton || obj == exitItem) { //Í˳ö³ÌÐò int j=JOptionPane.showConfirmDialog( this,"ÕæµÄÒªÍ˳öÂð?","Í˳ö", JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE); if (j == JOptionPane.YES_OPTION){ stopService(); System.exit(0); } } else if (obj == helpItem) { //²Ëµ¥À¸ÖеİïÖú //µ÷³ö°ïÖú¶Ô»°¿ò Help helpDialog = new Help(this); helpDialog.show(); } else if (obj == sysMessage || obj == sysMessageButton) { //·¢ËÍϵͳÏûÏ¢ sendSystemMessage(); } } /** * Æô¶¯·þÎñ¶Ë */ public void startService(){ try{ serverSocket = new ServerSocket(port,10); messageShow.append("·þÎñ¶ËÒѾ­Æô¶¯£¬ÔÚ"+port+"¶Ë¿ÚÕìÌý...\n"); startServer.setEnabled(false); startItem.setEnabled(false); portSet.setEnabled(false); portItem.setEnabled(false); stopServer .setEnabled(true); stopItem .setEnabled(true); sysMessage.setEnabled(true); } catch (Exception e){ //System.out.println(e); } userLinkList = new UserLinkList(); listenThread = new ServerListen(serverSocket,combobox, messageShow,showStatus,userLinkList); listenThread.start(); } /** * ¹Ø±Õ·þÎñ¶Ë */ public void stopService(){ try{ //ÏòËùÓÐÈË·¢ËÍ·þÎñÆ÷¹Ø±ÕµÄÏûÏ¢ sendStopToAll(); listenThread.isStop = true; serverSocket.close(); int count = userLinkList.getCount(); int i =0; while( i < count){ Node node = userLinkList.findUser(i); node.input .close(); node.output.close(); node.socket.close(); i ++; } stopServer .setEnabled(false); stopItem .setEnabled(false); startServer.setEnabled(true); startItem.setEnabled(true); portSet.setEnabled(true); portItem.setEnabled(true); sysMessage.setEnabled(false); messageShow.append("·þÎñ¶ËÒѾ­¹Ø±Õ\n"); combobox.removeAllItems(); combobox.addItem("ËùÓÐÈË"); } catch(Exception e){ //System.out.println(e); } } /** * ÏòËùÓÐÈË·¢ËÍ·þÎñÆ÷¹Ø±ÕµÄÏûÏ¢ */ public void sendStopToAll(){ int count = userLinkList.getCount(); int i = 0; while(i < count){ Node node = userLinkList.findUser(i); if(node == null) { i ++; continue; } try{ node.output.writeObject("·þÎñ¹Ø±Õ"); node.output.flush(); } catch (Exception e){ //System.out.println("$$$"+e); } i++; } } /** * ÏòËùÓÐÈË·¢ËÍÏûÏ¢ */ public void sendMsgToAll(String msg){ int count = userLinkList.getCount();//Óû§×ÜÊý int i = 0; while(i < count){ Node node = userLinkList.findUser(i); if(node == null) { i ++; continue; } try{ node.output.writeObject("ϵͳÐÅÏ¢"); node.output.flush(); node.output.writeObject(msg); node.output.flush(); } catch (Exception e){ //System.out.println("@@@"+e); } i++; } sysMessage.setText(""); } /** * Ïò¿Í»§¶ËÓû§·¢ËÍÏûÏ¢ */ public void sendSystemMessage(){ String toSomebody = combobox.getSelectedItem().toString(); String message = sysMessage.getText() + "\n"; messageShow.append(message); //ÏòËùÓÐÈË·¢ËÍÏûÏ¢ if(toSomebody.equalsIgnoreCase("ËùÓÐÈË")){ sendMsgToAll(message); } else{ //Ïòij¸öÓû§·¢ËÍÏûÏ¢ Node node = userLinkList.findUser(toSomebody); try{ node.output.writeObject("ϵͳÐÅÏ¢"); node.output.flush(); node.output.writeObject(message); node.output.flush(); } catch(Exception e){ //System.out.println("!!!"+e); } sysMessage.setText("");//½«·¢ËÍÏûÏ¢À¸µÄÏûÏ¢Çå¿Õ } } public static void main(String[] args) { new ChatServer(); } } package liaotian; import java.io.*; import java.net.*; import javax.swing.*; /* * 聊天客户端消息收发类 */ public class ClientReceive extends Thread { private JComboBox combobox; private JTextArea textarea; Socket socket; ObjectOutputStream output; ObjectInputStream input; JTextField showStatus; public ClientReceive(Socket socket,ObjectOutputStream output, ObjectInputStream input,JComboBox combobox,JTextArea textarea,JTextField showStatus){ this.socket = socket; this.output = output; this.input = input; this.combobox = combobox; this.textarea = textarea; this.showStatus = showStatus; } public void run(){ while(!socket.isClosed()){ try{ String type = (String)input.readObject(); if(type.equalsIgnoreCase("系统信息")){ String sysmsg = (String)input.readObject(); textarea.append("系统信息: "+sysmsg); } else if(type.equalsIgnoreCase("服务关闭")){ output.close(); input.close(); socket.close(); textarea.append("服务器已关闭!\n"); break; } else if(type.equalsIgnoreCase("聊天信息")){ String message = (String)input.readObject(); textarea.append(message); } else if(type.equalsIgnoreCase("用户列表")){ String userlist = (String)input.readObject(); String usernames[] = userlist.split("\n"); combobox.removeAllItems(); int i =0; combobox.addItem("所有人"); while(i < usernames.length){ combobox.addItem(usernames[i]); i ++; } combobox.setSelectedIndex(0); showStatus.setText("在线用户 " + usernames.length + " 人"); } } catch (Exception e ){ System.out.println(e); } } } } package liaotian; import java.awt.*; import java.awt.event.*; import java.net.*; import javax.swing.*; /** * 生成连接信息输入的对话框 * 让用户输入连接服务器的IP和端口 */ public class ConnectConf extends JDialog { /** * */ private static final long serialVersionUID = 1L; JPanel panelUserConf = new JPanel(); JButton save = new JButton(); JButton cancel = new JButton(); JLabel DLGINFO=new JLabel(" 默认连接设置为 127.0.0.1:8888"); JPanel panelSave = new JPanel(); JLabel message = new JLabel(); String userInputIp; int userInputPort; JTextField inputIp; JTextField inputPort; public ConnectConf(JFrame frame,String ip,int port) { super(frame, true); this.userInputIp = ip; this.userInputPort = port; try { jbInit(); } catch (Exception e) { e.printStackTrace(); } //设置运行位置,使对话框居中 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation( (int) (screenSize.width - 400) / 2 + 50, (int) (screenSize.height - 600) / 2 + 150); this.setResizable(false); } private void jbInit() throws Exception { this.setSize(new Dimension(300, 130)); this.setTitle("连接设置"); message.setText(" 请输入服务器的IP地址:"); inputIp = new JTextField(10); inputIp.setText(userInputIp); inputPort = new JTextField(4); inputPort.setText(""+userInputPort); save.setText("保存"); cancel.setText("取消"); panelUserConf.setLayout(new GridLayout(2,2,1,1)); panelUserConf.add(message); panelUserConf.add(inputIp); panelUserConf.add(new JLabel(" 请输入服务器的端口号:")); panelUserConf.add(inputPort); panelSave.add(new Label(" ")); panelSave.add(save); panelSave.add(cancel); panelSave.add(new Label(" ")); Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(panelUserConf, BorderLayout.NORTH); contentPane.add(DLGINFO, BorderLayout.CENTER); contentPane.add(panelSave, BorderLayout.SOUTH); //保存按钮的事件处理 save.addActionListener( new ActionListener() { public void actionPerformed (ActionEvent a) { int savePort; //判断端口号是否合法 try{ userInputIp = "" + InetAddress.getByName(inputIp.getText()); userInputIp = userInputIp.substring(1); } catch(UnknownHostException e){ DLGINFO.setText( " 错误的IP地址!"); return; } //userInputIp = inputIP; //判断端口号是否合法 try{ savePort = Integer.parseInt(inputPort.getText()); if(savePort<1 || savePort>65535){ DLGINFO.setText(" 侦听端口必须是0-65535之间的整数!"); inputPort.setText(""); return; } userInputPort = savePort; dispose(); } catch(NumberFormatException e){ DLGINFO.setText(" 错误的端口号,端口号请填写整数!"); inputPort.setText(""); return; } } } ); //关闭对话框时的操作 this.addWindowListener( new WindowAdapter(){ public void windowClosing(WindowEvent e){ DLGINFO.setText(" 默认连接设置为 127.0.0.1:8888"); } } ); //取消按钮的事件处理 cancel.addActionListener( new ActionListener(){ public void actionPerformed(ActionEvent e){ DLGINFO.setText(" 默认连接设置为 127.0.0.1:8888"); dispose(); } }); } } package liaotian; import java.awt.*; import java.awt.event.*; import java.net.*; import javax.swing.*; import javax.swing.border.*; /** * 生成设置对话框的类 */ public class Help extends JDialog { /** * */ private static final long serialVersionUID = 2444646568765499416L; JPanel titlePanel = new JPanel(); JPanel contentPanel = new JPanel(); JPanel closePanel = new JPanel(); JButton close = new JButton(); JLabel title = new JLabel("聊天室服务端帮助"); JTextArea help = new JTextArea(); Color bg = new Color(255,255,255); public Help(JFrame frame) { super(frame, true); try { jbInit(); } catch (Exception e) { e.printStackTrace(); } //设置运行位置,使对话框居中 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation( (int) (screenSize.width - 400) / 2, (int) (screenSize.height - 320) / 2); this.setResizable(false); } private void jbInit() throws Exception { this.setSize(new Dimension(400, 200)); this.setTitle("帮助"); titlePanel.setBackground(bg);; contentPanel.setBackground(bg); closePanel.setBackground(bg); help.setText("1、设置服务端的侦听端口(默认端口为8888)。\n"+ "2、点击 启动服务 按钮便可在指定的端口启动服务。\n"+ "3、选择需要接受消息的用户,在消息栏中写入消息,之后便可发送消息。\n"+ "4、信息状态栏中显示服务器当前的启动与停止状态、"+ "用户发送的消息和\n 服务器端发送的系统消息。"); help.setEditable(false); titlePanel.add(new Label(" ")); titlePanel.add(title); titlePanel.add(new Label(" ")); contentPanel.add(help); closePanel.add(new Label(" ")); closePanel.add(close); closePanel.add(new Label(" ")); Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(titlePanel, BorderLayout.NORTH); contentPane.add(contentPanel, BorderLayout.CENTER); contentPane.add(closePanel, BorderLayout.SOUTH); close.setText("关闭"); //事件处理 close.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); } } package liaotian; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 生成设置对话框的类 */ public class Help1 extends JDialog { /** * */ private static final long serialVersionUID = 1L; JPanel titlePanel = new JPanel(); JPanel contentPanel = new JPanel(); JPanel closePanel = new JPanel(); JButton close = new JButton(); JLabel title = new JLabel("聊天室客户端帮助"); JTextArea help = new JTextArea(); Color bg = new Color(255,255,255); public Help1(JFrame frame) { super(frame, true); try { jbInit(); } catch (Exception e) { e.printStackTrace(); } //设置运行位置,使对话框居中 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation( (int) (screenSize.width - 400) / 2 + 25, (int) (screenSize.height - 320) / 2); this.setResizable(false); } private void jbInit() throws Exception { this.setSize(new Dimension(350, 270)); this.setTitle("帮助"); titlePanel.setBackground(bg);; contentPanel.setBackground(bg); closePanel.setBackground(bg); help.setText("1、设置所要连接服务端的IP地址和端口"+ "(默认设置为\n 127.0.0.1:8888)。\n"+ "2、输入你的用户名(默认设置为:狂狂)。\n"+ "3、点击“登录”便可以连接到指定的服务器;\n"+ " 点击“注销”可以和服务器端开连接。\n"+ "4、选择需要接受消息的用户,在消息栏中写入消息,\n"+ " 同时选择表情,之后便可发送消息。\n"); help.setEditable(false); titlePanel.add(new Label(" ")); titlePanel.add(title); titlePanel.add(new Label(" ")); contentPanel.add(help); closePanel.add(new Label(" ")); closePanel.add(close); closePanel.add(new Label(" ")); Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(titlePanel, BorderLayout.NORTH); contentPane.add(contentPanel, BorderLayout.CENTER); contentPane.add(closePanel, BorderLayout.SOUTH); close.setText("关闭"); //事件处理 close.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); } } package liaotian; import java.io.*; import java.net.*; /** * 用户链表的结点类 */ public class Node { String username = null; Socket socket = null; ObjectOutputStream output = null; ObjectInputStream input = null; Node next = null; } package liaotian; import javax.swing.*; import java.net.*; import java.awt.*; import java.awt.*; import java.awt.event.*; import javax.swing.border.*; /** * 生成端口设置对话框的类 */ public class PortConf extends JDialog { JPanel panelPort = new JPanel(); JButton save = new JButton(); JButton cancel = new JButton(); public static JLabel DLGINFO=new JLabel( " 默认端口号为:8888"); JPanel panelSave = new JPanel(); JLabel message = new JLabel(); public static JTextField portNumber ; public PortConf(JFrame frame) { super(frame, true); try { jbInit(); } catch (Exception e) { e.printStackTrace(); } //设置运行位置,使对话框居中 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation( (int) (screenSize.width - 400) / 2 + 50, (int) (screenSize.height - 600) / 2 + 150); this.setResizable(false); } private void jbInit() throws Exception { this.setSize(new Dimension(300, 120)); this.setTitle("端口设置"); message.setText("请输入侦听的端口号:"); portNumber = new JTextField(10); portNumber.setText(""+ChatServer.port); save.setText("保存"); cancel.setText("取消"); panelPort.setLayout(new FlowLayout()); panelPort.add(message); panelPort.add(portNumber); panelSave.add(new Label(" ")); panelSave.add(save); panelSave.add(cancel); panelSave.add(new Label(" ")); Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(panelPort, BorderLayout.NORTH); contentPane.add(DLGINFO, BorderLayout.CENTER); contentPane.add(panelSave, BorderLayout.SOUTH); //保存按钮的事件处理 save.addActionListener( new ActionListener() { public void actionPerformed (ActionEvent a) { int savePort; try{ savePort=Integer.parseInt(PortConf.portNumber.getText()); if(savePort<1 || savePort>65535){ PortConf.DLGINFO.setText(" 侦听端口必须是0-65535之间的整数!"); PortConf.portNumber.setText(""); return; } ChatServer.port = savePort; dispose(); } catch(NumberFormatException e){ PortConf.DLGINFO.setText(" 错误的端口号,端口号请填写整数!"); PortConf.portNumber.setText(""); return; } } } ); //关闭对话框时的操作 this.addWindowListener( new WindowAdapter(){ public void windowClosing(WindowEvent e){ DLGINFO.setText(" 默认端口号为:8888"); } } ); //取消按钮的事件处理 cancel.addActionListener( new ActionListener(){ public void actionPerformed(ActionEvent e){ DLGINFO.setText(" 默认端口号为:8888"); dispose(); } }); } } package liaotian; import java.net.*; import java.awt.*; import java.awt.*; import javax.swing.event.*; import javax.swing.*; import java.io.*; public class ServerListen extends Thread { ServerSocket server; JComboBox combobox; JTextArea textarea; JTextField textfield; UserLinkList userLinkList;//用户链表 Node client; ServerReceive recvThread; public boolean isStop; /* * 聊天服务端的用户上线于下线侦听类 */ public ServerListen(ServerSocket server,JComboBox combobox, JTextArea textarea,JTextField textfield,UserLinkList userLinkList){ this.server = server; this.combobox = combobox; this.textarea = textarea; this.textfield = textfield; this.userLinkList = userLinkList; isStop = false; } public void run(){ while(!isStop && !server.isClosed()){ try{ client = new Node(); client.socket = server.accept(); client.output = new ObjectOutputStream(client.socket.getOutputStream()); client.output.flush(); client.input = new ObjectInputStream(client.socket.getInputStream()); client.username = (String)client.input.readObject(); //显示提示信息 combobox.addItem(client.username); userLinkList.addUser(client); textarea.append("用户 " + client.username + " 上线" + "\n"); textfield.setText("在线用户" + userLinkList.getCount() + "人\n"); recvThread = new ServerReceive(textarea,textfield, combobox,client,userLinkList); recvThread.start(); } catch(Exception e){ } } } } package liaotian; import javax.swing.*; import java.io.*; import java.net.*; public class ServerReceive extends Thread { JTextArea textarea; JTextField textfield; JComboBox combobox; Node client; UserLinkList userLinkList;//用户链表 public boolean isStop; public ServerReceive(JTextArea textarea,JTextField textfield, JComboBox combobox,Node client,UserLinkList userLinkList){ this.textarea = textarea; this.textfield = textfield; this.client = client; this.userLinkList = userLinkList; this.combobox = combobox; isStop = false; } public void run(){ //向所有人发送用户的列表 sendUserList(); while(!isStop && !client.socket.isClosed()){ try{ String type = (String)client.input.readObject(); if(type.equalsIgnoreCase("聊天信息")){ String toSomebody = (String)client.input.readObject(); String status = (String)client.input.readObject(); String action = (String)client.input.readObject(); String message = (String)client.input.readObject(); String msg = client.username +" "+ action + "对 " + toSomebody + " 说 : " + message + "\n"; if(status.equalsIgnoreCase("悄悄话")){ msg = " [悄悄话] " + msg; } textarea.append(msg); if(toSomebody.equalsIgnoreCase("所有人")){ sendToAll(msg);//向所有人发送消息 } else{ try{ client.output.writeObject("聊天信息"); client.output.flush(); client.output.writeObject(msg); client.output.flush(); } catch (Exception e){ //System.out.println("###"+e); } Node node = userLinkList.findUser(toSomebody); if(node != null){ node.output.writeObject("聊天信息"); node.output.flush(); node.output.writeObject(msg); node.output.flush(); } } } else if(type.equalsIgnoreCase("用户下线")){ Node node = userLinkList.findUser(client.username); userLinkList.delUser(node); String msg = "用户 " + client.username + " 下线\n"; int count = userLinkList.getCount(); combobox.removeAllItems(); combobox.addItem("所有人"); int i = 0; while(i < count){ node = userLinkList.findUser(i); if(node == null) { i ++; continue; } combobox.addItem(node.username); i++; } combobox.setSelectedIndex(0); textarea.append(msg); textfield.setText("在线用户" + userLinkList.getCount() + "人\n"); sendToAll(msg);//向所有人发送消息 sendUserList();//重新发送用户列表,刷新 break; } } catch (Exception e){ //System.out.println(e); } } } /* * 向所有人发送消息 */ public void sendToAll(String msg){ int count = userLinkList.getCount(); int i = 0; while(i < count){ Node node = userLinkList.findUser(i); if(node == null) { i ++; continue; } try{ node.output.writeObject("聊天信息"); node.output.flush(); node.output.writeObject(msg); node.output.flush(); } catch (Exception e){ //System.out.println(e); } i++; } } /* * 向所有人发送用户的列表 */ public void sendUserList(){ String userlist = ""; int count = userLinkList.getCount(); int i = 0; while(i < count){ Node node = userLinkList.findUser(i); if(node == null) { i ++; continue; } userlist += node.username; userlist += '\n'; i++; } i = 0; while(i < count){ Node node = userLinkList.findUser(i); if(node == null) { i ++; continue; } try{ node.output.writeObject("用户列表"); node.output.flush(); node.output.writeObject(userlist); node.output.flush(); } catch (Exception e){ //System.out.println(e); } i++; } } } package liaotian; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 生成用户信息输入对话框的类 * 让用户输入自己的用户名 */ public class UserConf extends JDialog { /** * */ private static final long serialVersionUID = 1L; JPanel panelUserConf = new JPanel(); JButton save = new JButton(); JButton cancel = new JButton(); JLabel DLGINFO=new JLabel(" 默认用户名为:狂狂"); JPanel panelSave = new JPanel(); JLabel message = new JLabel(); String userInputName; JTextField userName ; public UserConf(JFrame frame,String str) { super(frame, true); this.userInputName = str; try { jbInit(); } catch (Exception e) { e.printStackTrace(); } //设置运行位置,使对话框居中 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setLocation( (int) (screenSize.width - 400) / 2 + 50, (int) (screenSize.height - 600) / 2 + 150); this.setResizable(false); } private void jbInit() throws Exception { this.setSize(new Dimension(300, 120)); this.setTitle("用户设置"); message.setText("请输入用户名:"); userName = new JTextField(10); userName.setText(userInputName); save.setText("保存"); cancel.setText("取消"); panelUserConf.setLayout(new FlowLayout()); panelUserConf.add(message); panelUserConf.add(userName); panelSave.add(new Label(" ")); panelSave.add(save); panelSave.add(cancel); panelSave.add(new Label(" ")); Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(panelUserConf, BorderLayout.NORTH); contentPane.add(DLGINFO, BorderLayout.CENTER); contentPane.add(panelSave, BorderLayout.SOUTH); //保存按钮的事件处理 save.addActionListener( new ActionListener() { public void actionPerformed (ActionEvent a) { if(userName.getText().equals("")){ DLGINFO.setText( " 用户名不能为空!"); userName.setText(userInputName); return; } else if(userName.getText().length() > 15){ DLGINFO.setText(" 用户名长度不能大于15个字符!"); userName.setText(userInputName); return; } userInputName = userName.getText(); dispose(); } } ); //关闭对话框时的操作 this.addWindowListener( new WindowAdapter(){ public void windowClosing(WindowEvent e){ DLGINFO.setText(" 默认用户名为:狂狂"); } } ); //取消按钮的事件处理 cancel.addActionListener( new ActionListener(){ public void actionPerformed(ActionEvent e){ DLGINFO.setText(" 默认用户名为:狂狂"); dispose(); } }); } }

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享文档获得金币 ]
2 人已下载

下载文档

相关文档