最近需要学习下socket,就顺带做了个聊天的小demo。
基本是抄人家的,我加了个util类,优化了下。
有swing界面的,学生和初学者可以拿走学习下。
http://download.csdn.net/detail/sysmaid/3880649
贴部分代码。
服务器端 线程:
/** * 服务线程类 * @author JingHui * * create by 2011-11-24 下午1:38:10 */ class ServerThread extends Thread { private Socket socket; public ServerThread(Socket socket){ this.socket = socket; } public void run(){ try{ ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); while(true){ Vector v = null; try{ v = (Vector)ois.readObject(); }catch(Exception e){ e.printStackTrace(); System.out.println("=======与客户端通信出现错误======="); } if(v!=null && v.size()>0){ for(int i=0; i<v.size(); i++){ String info = (String)v.get(i); String key = ""; if(info.startsWith(ChatUtil.MSG_LOGIN)){ key = info.substring(7);//获得用户名 map.put(key, socket);//客户端添加至列表 ta_info.append(key + " login...\n"); Set<String> set = map.keySet(); Iterator<String> it = set.iterator(); while(it.hasNext()){//迭代map,向所有客户端发送登录信息 String reciveKey = it.next();//表示接收信息的key,即用户名 Socket s = map.get(reciveKey); PrintWriter pw = new PrintWriter(s.getOutputStream(), true); pw.println(info); pw.flush(); } }else if(info.startsWith(ChatUtil.MSG_EXIT)){//用户退出 key = info.substring(6);//获得退出用户的key ois.close(); socket.close(); map.remove(key); Set<String> set = map.keySet(); Iterator<String> it = set.iterator(); while(it.hasNext()){ String reciveKey = it.next(); Socket s = map.get(reciveKey); PrintWriter pw = new PrintWriter(s.getOutputStream(), true); pw.println(info); pw.flush(); } ta_info.append(key + " exit...\n"); return;//退出线程 }else if(info.startsWith(ChatUtil.MSG_USERLIST)){//传递当前在线用户列表 String userList = ""; Set<String> set = map.keySet(); Iterator<String> it = set.iterator(); while(it.hasNext()){ key = it.next(); userList += key + ","; } key = info.substring(10); Iterator<String> it2 = set.iterator(); while(it2.hasNext()){ String reciveKey = it2.next(); if(key.equals(reciveKey)){ Socket s = map.get(reciveKey); PrintWriter pw = new PrintWriter(s.getOutputStream(), true); pw.println(ChatUtil.MSG_USERLIST + userList); pw.flush(); } } }else{//正常的消息转发 String[] infos = ChatUtil.formatInfos(info); Set<String> set = map.keySet(); Iterator<String> it = set.iterator(); while(it.hasNext()){ String reciveKey = it.next(); if(reciveKey.equals(infos[1])){//寻找到接受者 Socket s = map.get(reciveKey); PrintWriter pw = new PrintWriter(s.getOutputStream(), true); pw.println(info);//原文转发,客户端进行处理 pw.flush(); } } }//end else }//end for }//end if v }//end while }catch(Exception e){ e.printStackTrace(); ta_info.append(socket + "退出异常。\n"); } } }//end class ServerThread
客户端界面:
/** * 构造函数 * 在构造中初始化界面 */ public ChatClientFrame(){ super(); this.setTitle("小兔聊天室客户端"); this.setBounds(100, 100, 385, 288); final JPanel panel = new JPanel(); this.getContentPane().add(panel, BorderLayout.SOUTH); final JLabel label = new JLabel(); label.setText("输入聊天内容"); panel.add(label); tf_send = new JTextField(); tf_send.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent arg0) { send();//调用发送方法 } }); tf_send.setPreferredSize(new Dimension(180, 25)); panel.add(tf_send);//发送消息区域 final JButton button = new JButton(); button.setText("发 送"); button.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ send(); } }); panel.add(button);//添加发送按钮 final JSplitPane splitPane = new JSplitPane(); splitPane.setDividerLocation(100);//分隔条的位置 this.getContentPane().add(splitPane, BorderLayout.CENTER); final JScrollPane scrollPane = new JScrollPane(); splitPane.setRightComponent(scrollPane); ta_info = new JTextArea(); ta_info.setFont(new Font("", Font.BOLD, 14)); scrollPane.setViewportView(ta_info);//信息显示区域 //-------显示用户列表 start------- final JScrollPane scrollPane1 = new JScrollPane(); userList = new JList(); userList.setModel(new DefaultComboBoxModel(new String[] {""})); scrollPane1.setViewportView(userList); splitPane.setLeftComponent(scrollPane1); //-------显示用户列表 end------- //-------显示用户登录 start------- final JPanel panel_1 = new JPanel(); final JLabel label_1 = new JLabel(); label_1.setText("用户名称:"); panel_1.add(label_1); tf_newUser = new JTextField(); tf_newUser.setPreferredSize(new Dimension(140, 25)); panel_1.add(tf_newUser); final JButton button_1 = new JButton(); button_1.setText("登 录"); button_1.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent arg0) {//进行登录操作 if(loginFlag){ JOptionPane.showConfirmDialog(null, "当前用户已登录"); return; } String userName = tf_newUser.getText().trim(); Vector<String> v = new Vector<String>(); v.add(ChatUtil.fittingLoginMsg(userName));//发送登录信息 try{ out.writeObject(v);//发送 out.flush(); }catch(Exception e){ e.printStackTrace(); } tf_newUser.setEnabled(false);//用户名不可修改 button_1.setVisible(false);//登录按钮隐藏 loginFlag = true; getOnlineUser(userName);//获取在线用户列表 } }); panel_1.add(button_1); final JButton button_2 = new JButton(); button_2.setText("退 出"); button_2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent arg0) { if(!loginFlag){//未登录 JOptionPane.showMessageDialog(null, "已退出或未登录!"); return; } String exitUser = tf_newUser.getText().trim(); Vector<String> v = new Vector<String>(); v.add(ChatUtil.fittingExitMsg(exitUser));//退出信息 try{ out.writeObject(v); out.flush(); }catch(Exception e){ e.printStackTrace(); } System.exit(0); } }); panel_1.add(button_2); this.getContentPane().add(panel_1, BorderLayout.NORTH); //-------显示用户登录 end------- //-------系统托盘 start------- if(SystemTray.isSupported()){ URL url = ChatClientFrame.class.getResource(ChatUtil.LOGO_IMAGE); ImageIcon i_con= new ImageIcon(url); Image image = i_con.getImage(); TrayIcon trayIcon = new TrayIcon(image); trayIcon.addMouseListener(new MouseAdapter(){ public void mouseClicked(MouseEvent e) { if(e.getClickCount()==2){ showFrame();//显示界面 } } }); trayIcon.setToolTip("小兔聊天"); PopupMenu popupMenu = new PopupMenu(); MenuItem exitMenu = new MenuItem("退出"); exitMenu.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent arg0) { String exitUser = tf_newUser.getText().trim(); Vector<String> v = new Vector<String>(); v.add(ChatUtil.fittingExitMsg(exitUser));//退出信息 try{ out.writeObject(v); out.flush(); out.close(); socket.close(); }catch(Exception e){ e.printStackTrace(); } System.exit(0); } }); popupMenu.add(exitMenu); trayIcon.setPopupMenu(popupMenu); SystemTray systemTray = SystemTray.getSystemTray(); try { systemTray.add(trayIcon); } catch (Exception e1) { e1.printStackTrace(); } } //-------系统托盘 end------- }