java学习之即时通信项目实战

 项目总结:这次项目主要是根据视频来的,结果跟到一半感觉跟不上,慢慢自己有了自己的想法,决定自己先不看学习视频,自己先试着写。

  总结写前面,算是写的第一个项目吧。项目中遇到几点问题,首先Scoket对象创建后,服务器端和客户端不能同时创建输入流,否者会引起堵塞。

  然后,读入流应该重新创建个线程做等待写入服务,因为读入流会引起当前线程进入阻塞状态。

     还有一个用户线程对应一个服务线程,不是多个用户线程对应一个服务线程。

     对对象的操作应该由那个对象本身提供操作方法,比如操作UI界面的变化应该由界面本身提拱。

  最后最重要的是写代码之前应该先画个流程图,写代码时参数乱传的,哪里需要就调参数过来。导致思路不清.

首先是需求分析:

  本次项目是模拟及时通信中最基本的功能,类似QQ的应用.

  项目分为:

   (1)服务器端:

    服务器端主要负责用户管理,消息转发功能

   (2) 客户端:

    客户端主要负责用户间的消息发送

详细设计

服务器端

  1、登录服务器后,进行客户端的监听,如有客户端连接,启动用户服务线程,与客户端进行交互。

  2、如客户端向所有人发送消息,服务器将向所有在线用户广播该消息。

      3、如客户端向指定人发送消息,服务器将查找接收人用户线程后转发消息。

      4、用户登录后,向所有人更新用户列表。

客户端:

1、用户登录功能。

2、登录后用户可以看到在线用户列表

3 、向指定人发送消息

4、向所有人发送消息

代码的实现

首先,先构建界面图形出来

 

上面左边是用户界面(服务器界面和用户界面一样),右边是登录界面

由于全用手写代码比较麻烦,我用了可视化UI插件;

画出来如下图

界面做出来了,然后构建对象模型,

这里主要需要信息对象,和用户对象;

信息对象又分,登录信息,发送信息和退出信息。这里我把登录信息单独用一个对象构建,因为保存了帐号密码,以后好增加登录验证功能。

然后就是逻辑功能的实现了。

这里我发现看似简单的功能,实现起来还是有点麻烦的。学会了一点就是要模块化。不然自己很容易搞迷糊。

直接上代码:

客户端代码

  1 package com.gh.Client;
  2 
  3 import java.awt.Toolkit;
  4 
  5 public class ClientFrame {
  6 
  7     private JFrame Clientframe;
  8     private JTextField textField;
  9     private String username;
 10     private JTextArea textArea = null;
 11     private JList<String> list = null;
 12     private DefaultListModel<String> model = null;
 13     private UserService us;
 14 
 15     // 初始化用户列表
 16     public void InitUserList() {
 17         model = new DefaultListModel<String>();
 18         model.addElement("所有人");
 19         list.setModel(model);
 20     }
 21 
 22     // 添加用户到在线列表
 23     public void AddUserToList(String username) {
 24         // 拆了东墙补西墙。。。之前添加的要全删了,再添加一次
 25         model.removeAllElements();
 26         model.addElement("所有人");
 27         String[] str = username.split(",");
 28         for (String s : str) {
 29             model.addElement(s);
 30         }
 31         //list.setModel(model);
 32     }
 33 
 34     public void updateText(String text) {
 35         StringBuffer sb = new StringBuffer();
 36         sb.append(textArea.getText()).append(DateUtil.getTime() + "\n").append(text).append("\n");
 37         textArea.setText(sb.toString());
 38     }
 39     public void DelUser(String username){
 40         model.removeElement(username);
 41     }
 42 
 43     /**
 44      * Create the application.
 45      */
 46     public ClientFrame(String username,UserService us) {
 47         this.username = username;
 48         this.us=us;
 49         initialize();
 50         // 初始化用户列表
 51         InitUserList();
 52     }
 53 
 54     /**
 55      * Initialize the contents of the frame.
 56      */
 57     private void initialize() {
 58         Clientframe = new JFrame();
 59         Clientframe.addWindowListener(new WindowAdapter() {
 60             @Override
 61             public void windowClosing(WindowEvent e) {
 62                 Info info=new Info();
 63                 info.setFromUser(username);
 64                 info.setInfoType(EnumInfoType.EXIT);
 65                 us.send(info);
 66                 us.setFlag(false);
 67                 Clientframe.dispose();
 68             }
 69         });
 70         Clientframe.setVisible(true);
 71         Clientframe
 72                 .setIconImage(Toolkit.getDefaultToolkit().getImage(ClientFrame.class.getResource("/com/gh/res/1.png")));
 73         Clientframe.setTitle("\u804A\u804A-\u5BA2\u6237\u7AEF");
 74         Toolkit tk = Toolkit.getDefaultToolkit();
 75         Dimension d = tk.getScreenSize();
 76         int x = (int) (d.getWidth() - 534) / 2;
 77         int y = (int) (d.getHeight() - 383) / 2;
 78         Clientframe.setBounds(x, y, 534, 383);
 79         Clientframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 80         Clientframe.getContentPane().setLayout(new BorderLayout(0, 0));
 81 
 82         JLabel label = new JLabel("当前用户是:" + username);
 83         Clientframe.getContentPane().add(label, BorderLayout.NORTH);
 84 
 85         JPanel jpanel = new JPanel();
 86         Clientframe.getContentPane().add(jpanel, BorderLayout.EAST);
 87         jpanel.setLayout(new BorderLayout(0, 0));
 88 
 89         JLabel lblNewLabel = new JLabel("--\u5728\u7EBF\u7528\u6237\u5217\u8868--");
 90         jpanel.add(lblNewLabel, BorderLayout.NORTH);
 91 
 92         list = new JList<String>();
 93         jpanel.add(list, BorderLayout.CENTER);
 94 
 95         JScrollPane scrollPane = new JScrollPane();
 96         Clientframe.getContentPane().add(scrollPane, BorderLayout.CENTER);
 97 
 98         textArea = new JTextArea();
 99         scrollPane.setViewportView(textArea);
100 
101         JPanel panel = new JPanel();
102         Clientframe.getContentPane().add(panel, BorderLayout.SOUTH);
103         panel.setLayout(new BorderLayout(0, 0));
104 
105         JLabel lblNewLabel_1 = new JLabel("\u8BF7\u8F93\u5165\uFF1A");
106         panel.add(lblNewLabel_1, BorderLayout.WEST);
107 
108         textField = new JTextField();
109         panel.add(textField, BorderLayout.CENTER);
110         textField.setColumns(10);
111 
112         JButton button = new JButton("\u53D1\u9001");
113         button.addActionListener(new ActionListener() {
114             public void actionPerformed(ActionEvent e) {
115                 // 获取发送信息
116                 String sendContent = textField.getText().trim();
117                 // 获取发送对象
118                 Info info = new Info();
119                 info.setFromUser(username);
120                 info.setToUser((String) list.getSelectedValue());
121                 info.setContent(sendContent);
122                 info.setInfoType(EnumInfoType.SEND_INFO);
123                 System.out.println(info.getToUser());
124                 // 首先判断发送对象是否为空
125                 if ("".equals(info.getToUser()) || info.getToUser() == null) {
126                     JOptionPane.showMessageDialog(Clientframe, "请选择发送对象");
127                     return;
128                 } else if (info.getToUser().equals(username)) {
129                     JOptionPane.showMessageDialog(Clientframe, "不能对自己发送");
130                     return;
131                 } else if (info.getContent().equals("") || info.getContent() == null) {
132                     JOptionPane.showMessageDialog(Clientframe, "内容不能为空");
133                     return;
134                 } else
135                     us.send(info);
136                 textField.setText("");
137             }
138         });
139         panel.add(button, BorderLayout.EAST);
140     }
141 
142 }
ClientFrame
  1 package com.gh.Client;
  2 
  3 import java.awt.Dimension;
  4 
  5 @SuppressWarnings("unused")
  6 public class LoginFrame {
  7 
  8     private JFrame frame;
  9     private JTextField id;
 10     private JPasswordField pwd;
 11 
 12 
 13     /**
 14      * Launch the application.
 15      */
 16     public static void main(String[] args) {
 17         EventQueue.invokeLater(new Runnable() {
 18             public void run() {
 19                 try {
 20                     LoginFrame window = new LoginFrame();
 21                     window.frame.setVisible(true);
 22                     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
 23                 } catch (Exception e) {
 24                     e.printStackTrace();
 25                 }
 26             }
 27         });
 28     }
 29 
 30     /**
 31      * Create the application.
 32      */
 33     public LoginFrame() {
 34         initialize();
 35     }
 36 
 37     /**
 38      * Initialize the contents of the frame.
 39      */
 40     private void initialize() {
 41         frame =  new JFrame();
 42         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 43         frame.setVisible(true);
 44         frame.setIconImage(Toolkit.getDefaultToolkit().getImage(LoginFrame.class.getResource("/com/gh/res/1.png")));
 45         Toolkit tk=Toolkit.getDefaultToolkit();
 46         Dimension d=tk.getScreenSize();
 47         int x=(int)(d.getWidth()-379)/2;
 48         int y=(int)(d.getHeight()-171)/2;
 49         frame.setResizable(false);
 50         frame.setTitle("\u767B\u5F55");
 51         frame.setBounds(x, y, 379, 171);
 52         frame.getContentPane().setLayout(new GridLayout(3, 1, 20, 5));
 53         
 54         JPanel panel = new JPanel();
 55         frame.getContentPane().add(panel);
 56         FlowLayout fl_panel = new FlowLayout(FlowLayout.CENTER, 5, 10);
 57         fl_panel.setAlignOnBaseline(true);
 58         panel.setLayout(fl_panel);
 59         
 60         JLabel label = new JLabel("\u7528\u6237\u5E10\u53F7\uFF1A");
 61         label.setFont(new Font("微软雅黑", Font.PLAIN, 15));
 62         panel.add(label);
 63         
 64         id = new JTextField();
 65         panel.add(id);
 66         id.setColumns(15);
 67         
 68         
 69         JPanel panel_1 = new JPanel();
 70         FlowLayout flowLayout = (FlowLayout) panel_1.getLayout();
 71         flowLayout.setAlignOnBaseline(true);
 72         flowLayout.setVgap(10);
 73         frame.getContentPane().add(panel_1);
 74         
 75         JLabel label_1 = new JLabel("\u7528\u6237\u5BC6\u7801\uFF1A");
 76         label_1.setFont(new Font("微软雅黑", Font.PLAIN, 15));
 77         panel_1.add(label_1);
 78         
 79         pwd = new JPasswordField();
 80         pwd.setColumns(15);
 81         panel_1.add(pwd);
 82         
 83         JPanel panel_2 = new JPanel();
 84         FlowLayout flowLayout_1 = (FlowLayout) panel_2.getLayout();
 85         flowLayout_1.setVgap(6);
 86         frame.getContentPane().add(panel_2);
 87         
 88         JButton button = new JButton("\u767B\u5F55");
 89         button.addActionListener(new ActionListener() {
 90             public void actionPerformed(ActionEvent arg0) {
 91                 String username=id.getText().trim();
 92                 String password=new String(pwd.getPassword());
 93                 if("".equals(username)||username==null||"".equals(password)||password==null){
 94                     JOptionPane.showMessageDialog(frame, "用户名和密码不能为空");
 95                     return;
 96                 }
 97                 new UserService().login(username, password,frame);
 98             }
 99         });
100         button.setFont(new Font("微软雅黑", Font.PLAIN, 15));
101         panel_2.add(button);
102         
103         JButton button_1 = new JButton("\u9000\u51FA");
104         button_1.addActionListener(new ActionListener() {
105             public void actionPerformed(ActionEvent e) {
106                 int v=JOptionPane.showConfirmDialog(frame, "真的要退出吗", "退出", JOptionPane.YES_NO_OPTION);
107                 if(v==JOptionPane.YES_OPTION)System.exit(0);
108             }
109         });
110         button_1.setFont(new Font("微软雅黑", Font.PLAIN, 15));
111         panel_2.add(button_1);
112     }
113 
114     
115 }
LoginFrame
 1 package com.gh.Client;
 2 
 3 import java.io.IOException;
 4 import java.io.ObjectInputStream;
 5 import java.io.ObjectOutputStream;
 6 import java.net.Socket;
 7 
 8 import javax.swing.JFrame;
 9 import javax.swing.JOptionPane;
10 
11 import com.gh.model.Info;
12 import com.gh.model.LoginInfo;
13 
14 public class UserService {
15     private LoginInfo logininfo = null;
16     private ClientFrame clientframe = null;
17     private boolean flag = true;
18     private Info getInfo = null;
19     public boolean isFlag() {
20         return flag;
21     }
22     public void setFlag(boolean flag) {
23         this.flag = flag;
24     }
25     private ObjectOutputStream bw;
26     private ObjectInputStream br;
27     public void login(final String username, final String password, final JFrame frame) {
28         //接收消息线程
29         Thread t=new Thread(new Runnable() {
30             @Override
31             public void run() {
32                 try {
33                     Socket sk = new Socket("192.168.1.102", 8000);
34                     //这里被堵了好久,必须要先创建bw再创建br,因为scoket不许客户端和服务端同时创建输入流否者会堵塞Scoket通道
35                     bw =new ObjectOutputStream(sk.getOutputStream());
36                     br = new ObjectInputStream(sk.getInputStream());
37                     logininfo = new LoginInfo(username, password);
38                     bw.writeObject(logininfo);//向服务器发送登录信息
39                     bw.flush();
40                     //从服务接收登录信息
41                     LoginInfo objflag = (LoginInfo) br.readObject();
42                     if (objflag.isFlag()) {// 如果可以登录
43                         // 创建聊天界面
44                         clientframe = new ClientFrame(logininfo.getName(),UserService.this);
45                         // 聊天界面显示欢迎信息
46                         clientframe.updateText("服务器:欢迎登录!");
47                         frame.dispose();
48                         // 等待接收消息 
49                         while (isFlag()) {
50                             getInfo = new Info();
51                             getInfo = (Info) br.readObject();
52                             switch (getInfo.getInfoType()) {
53                             case SEND_INFO:
54                                 clientframe.updateText("用户:"+getInfo.getFromUser()+"说:"+getInfo.getContent());
55                                 break;
56                             case ADD_USER:
57                                 clientframe.AddUserToList(getInfo.getContent());
58                                 break;
59                             case EXIT:
60                                 clientframe.DelUser(getInfo.getFromUser());
61                                 clientframe.updateText("服务器:用户"+getInfo.getFromUser()+"下线了");
62                                 break;
63                             default:
64                                 break;
65                             }
66 
67                         }
68                     } else {
69                         JOptionPane.showMessageDialog(frame, "用户名或密码错误");
70                     }
71                 } catch (Exception e) {
72                     JOptionPane.showMessageDialog(frame, "服务器连接异常");
73                      //e.printStackTrace();
74                 }
75             }
76         });
77         t.start();
78     }
79     //发送消息线程
80     public void send(Info info){
81         try {
82             bw.writeObject(info);
83             bw.flush();
84         } catch (IOException e) {
85             e.printStackTrace();
86         }
87     }
88 }
UserService

服务端代码

  1 package com.gh.Sever;
  2 
  3 import java.awt.EventQueue;
  4 
  5 public class ServerFrame {
  6 
  7     private JFrame Severframe;
  8     private JTextField textField;
  9     private JTextArea textArea = null;
 10     private DefaultListModel<String> model=null;
 11     private JList<String> list=null;
 12     /**
 13      * Launch the application.
 14      */
 15     public static void main(String[] args) {
 16         EventQueue.invokeLater(new Runnable() {
 17             public void run() {
 18                 try {
 19                     ServerFrame window = new ServerFrame();
 20                     window.Severframe.setVisible(true);
 21                     // 设置UI风格为系统默认的风格
 22                     //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
 23                 } catch (Exception e) {
 24                     e.printStackTrace();
 25                 }
 26             }
 27         });
 28 
 29     }
 30     //初始化用户列表
 31     public void InitUserList(){
 32         model=new DefaultListModel<String>();
 33         model.addElement("所有人");
 34         list.setModel(model);
 35     }
 36     //添加用户到在线列表
 37     public void AddUserToList(String username){
 38         model.addElement(username);
 39         list.setModel(model);
 40     }
 41     public void updateText(String text) {
 42         StringBuffer sb = new StringBuffer();
 43         sb.append(textArea.getText()).append("\n").append(DateUtil.getTime()+"--")
 44             .append(text);
 45         textArea.setText(sb.toString());
 46     }
 47     public void DelUser(String username){
 48         model.removeElement(username);
 49     }
 50     /**
 51      * Create the application.
 52      */
 53     public ServerFrame() {
 54         initialize();
 55         // 启动服务
 56         startSever();
 57         //初始化用户列表
 58         InitUserList();
 59     }
 60 
 61     private void startSever() {
 62         textArea.setText("服务器已经启动,正在监听8000端口...");
 63         new Thread(new Runnable() {
 64             @Override
 65             public void run() {
 66                 new ServerService(ServerFrame.this).startSever();
 67             }
 68         }).start();
 69     }
 70 
 71     /**
 72      * Initialize the contents of the frame.
 73      */
 74     private void initialize() {
 75         Severframe = new JFrame();
 76         Severframe
 77                 .setIconImage(Toolkit.getDefaultToolkit().getImage(ServerFrame.class.getResource("/com/gh/res/1.png")));
 78         Severframe.setTitle("\u804A\u804A-\u670D\u52A1\u7AEF");
 79         Toolkit tk = Toolkit.getDefaultToolkit();
 80         Dimension d = tk.getScreenSize();
 81         int x = (int) (d.getWidth() - 534) / 2;
 82         int y = (int) (d.getHeight() - 383) / 2;
 83         Severframe.setBounds(x, y, 534, 383);
 84         Severframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 85         Severframe.getContentPane().setLayout(new BorderLayout(0, 0));
 86 
 87         JLabel label = new JLabel("\u670D\u52A1\u5668\u7AEF");
 88         Severframe.getContentPane().add(label, BorderLayout.NORTH);
 89 
 90         JPanel jpanel = new JPanel();
 91         Severframe.getContentPane().add(jpanel, BorderLayout.EAST);
 92         jpanel.setLayout(new BorderLayout(0, 0));
 93 
 94         JLabel lblNewLabel = new JLabel("--\u5728\u7EBF\u7528\u6237\u5217\u8868--");
 95         jpanel.add(lblNewLabel, BorderLayout.NORTH);
 96 
 97         list = new JList<String>();
 98         jpanel.add(list, BorderLayout.CENTER);
 99 
100         JScrollPane scrollPane = new JScrollPane();
101         Severframe.getContentPane().add(scrollPane, BorderLayout.CENTER);
102 
103         textArea = new JTextArea();
104         scrollPane.setViewportView(textArea);
105 
106         JPanel panel = new JPanel();
107         Severframe.getContentPane().add(panel, BorderLayout.SOUTH);
108         panel.setLayout(new BorderLayout(0, 0));
109 
110         JLabel lblNewLabel_1 = new JLabel("\u8BF7\u8F93\u5165\uFF1A");
111         panel.add(lblNewLabel_1, BorderLayout.WEST);
112 
113         textField = new JTextField();
114         panel.add(textField, BorderLayout.CENTER);
115         textField.setColumns(10);
116 
117         JButton button = new JButton("\u53D1\u9001");
118         panel.add(button, BorderLayout.EAST);
119     }
120 
121 }
ServerFrame
  1 package com.gh.Sever;
  2 
  3 import java.io.IOException;
  4 import java.io.ObjectInputStream;
  5 import java.io.ObjectOutputStream;
  6 import java.net.ServerSocket;
  7 import java.net.Socket;
  8 import java.util.Vector;
  9 import java.util.concurrent.ExecutorService;
 10 import java.util.concurrent.Executors;
 11 
 12 import com.gh.model.Info;
 13 import com.gh.model.LoginInfo;
 14 import com.gh.util.EnumInfoType;
 15 
 16 /**
 17  * 服务器客户端监听
 18  * 
 19  * @author ganhang
 20  */
 21 public class ServerService {
 22     private Info currInfo = null;
 23     private ServerFrame serFrame;
 24     private boolean flag;
 25     private UserServerThread ust;
 26     ExecutorService es = Executors.newScheduledThreadPool(1);
 27     // 保存所有在线用户服务线程
 28     private Vector<UserServerThread> userThreads;
 29 
 30     public ServerService(ServerFrame serFrame) {
 31         this.serFrame = serFrame;
 32     }
 33 
 34     public void startSever() {
 35         flag = true;
 36         try {
 37             ServerSocket server = new ServerSocket(8000);
 38             userThreads = new Vector<UserServerThread>();
 39             while (flag) {
 40                 Socket client = server.accept();
 41                 System.out.println("Server:有用户连接");
 42                 ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
 43                 ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
 44                 LoginInfo logininfo = (LoginInfo) ois.readObject();// 获取用户帐号密码
 45                 System.out.println(logininfo);
 46                 // 登录验证
 47                 if (UserLogin.islogin(logininfo.getName(), logininfo.getPwd())) {
 48                     logininfo.setFlag(true);
 49                     oos.writeObject(logininfo);// 发送确认登录信息
 50                     oos.flush();
 51                     // 保存当前用户信息
 52                     currInfo = new Info();
 53                     currInfo.setFromUser(logininfo.getName());
 54                     // 在服务器端显示用户登录信息
 55                     serFrame.updateText("用户" + logininfo.getName() + "--已上线!");
 56                     // 创建用户服务线程
 57                     UserServerThread ust = new UserServerThread(currInfo, ois, oos);// 创建用户服务进程
 58                     userThreads.add(ust);// 添加到进程池
 59                     es.execute(ust);// 启动线程
 60                 } else
 61                     oos.writeObject(logininfo);
 62             }
 63         } catch (IOException | ClassNotFoundException e) {
 64             e.printStackTrace();
 65         }
 66     }
 67 
 68     /**
 69      * 用户服务线程
 70      * 
 71      * @author ganhang
 72      */
 73     class UserServerThread implements Runnable {
 74         private Info info = null;
 75         private ObjectOutputStream oos;
 76         private ObjectInputStream ois;
 77 
 78         public UserServerThread(Info info, ObjectInputStream ois, ObjectOutputStream oos) {
 79             this.info = info;
 80             this.oos = oos;
 81             this.ois = ois;
 82         }
 83 
 84         @Override
 85         public void run() {
 86             // 更新服务器的在线用户列表
 87             serFrame.AddUserToList(currInfo.getFromUser());
 88             // 先获得在线用户的列表
 89             StringBuffer sb = new StringBuffer();
 90             for (UserServerThread u : userThreads) {
 91                 sb.append(u.info.getFromUser()).append(",");
 92             }
 93             System.out.println(sb.toString());
 94             // 首先向线程池里每个用户发送一个自己的在线用户列表
 95             for (UserServerThread usts : userThreads) {
 96                 try {
 97                     currInfo.setInfoType(EnumInfoType.ADD_USER);
 98                     currInfo.setContent(sb.toString());
 99                     usts.oos.writeObject(currInfo);// 注意要写那个线程的输出流
100                     usts.oos.flush();
101                 } catch (IOException e) {
102                     e.printStackTrace();
103                 }
104             }
105             // 等待接收用户信息
106             System.out.println(flag);
107             new Thread(new Wait(ois, oos)).start();
108 
109         }
110 
111         public void send(Info sendinfo) throws IOException {
112             oos.writeObject(sendinfo);
113             oos.flush();
114         }
115     }
116 
117     // 接收信息
118     class Wait implements Runnable {
119         private ObjectOutputStream oos;
120         private ObjectInputStream ois;
121         private boolean wait = true;
122 
123         public Wait(ObjectInputStream ois, ObjectOutputStream oos) {
124             this.oos = oos;
125             this.ois = ois;
126         }
127 
128         @Override
129         public void run() {
130             while (wait) {
131                 try {
132                     // 接收信息必须重开线程因为会把当前线程阻塞
133                     Info info = (Info) ois.readObject();
134                     System.out.println(Thread.currentThread().getName() + "收到一个send信息");
135                     System.out.println(info);
136                     switch (info.getInfoType()) {
137                     case SEND_INFO:
138                         if (info.getToUser().equals("所有人")) {
139                             for (UserServerThread user : userThreads) {
140                                 //这里容易发错人,注意每个用户都有一个服务线程,哪个用户要接收信息就由它的服务线程去发给它,其他用户的服务线程发不了。
141                                 if (!info.getFromUser().equals(user.info.getFromUser()))
142                                     user.send(info);
143                                 System.out.print(user.info.getFromUser() + "/");
144                             }
145                             System.out.println("消息发送名单");
146                         } else {
147                             for (UserServerThread user : userThreads) {
148                                 if (info.getToUser().equals(user.info.getFromUser())) {
149                                     user.send(info);
150                                 }
151                             }
152                         }
153                         break;
154                     case EXIT:
155                         serFrame.DelUser(info.getFromUser());
156                         serFrame.updateText("用户" + info.getFromUser() + "下线了");
157                         for (UserServerThread user : userThreads) {
158                             if (!info.getFromUser().equals(user.info.getFromUser())) {
159                                 user.send(info);
160                             } 
161                             //这里ust保存的是最后登录的用户的线程因为一直在被覆盖,
162                             //需要重新写如当前要删的
163                             else ust = user;
164                             System.out.print(user.info.getFromUser() + ",");
165                         }
166                         System.out.println("退出发送名单");
167                         // 删除服务器上的该在线用户
168                         wait = false;
169                         System.out.println("移除的用户:" + ust.info.getFromUser());
170                         //这里容易删错用户线程
171                         userThreads.remove(ust);
172                         break;
173                     default:
174                         break;
175                     }
176                 } catch (ClassNotFoundException | IOException e) {
177                      e.printStackTrace();
178                 }
179 
180             }
181         }
182     }
183 
184 }
ServerService
 1 package com.gh.Sever;
 2 /**
 3  * 登录验证,以后加数据库在写
 4  * @author ganhang
 5  */
 6 public class UserLogin {
 7     public static  boolean islogin(String name ,String pwd){
 8         return true;
 9     }
10 }
UserLogin

对象模型

 1 package com.gh.model;
 2 
 3 import java.io.Serializable;
 4 
 5 import com.gh.util.EnumInfoType;
 6 /**
 7  * 消息对象
 8  * @author ganhang
 9  *
10  */
11 public class Info implements Serializable{
12     private String fromUser;//信息来自哪
13     private String toUser;//发给谁
14     private String content;//内容
15     private EnumInfoType infoType;//信息类型
16     public String getFromUser() {
17         return fromUser;
18     }
19     public void setFromUser(String fromUser) {
20         this.fromUser = fromUser;
21     }
22     public String getToUser() {
23         return toUser;
24     }
25     public void setToUser(String toUser) {
26         this.toUser = toUser;
27     }
28 
29     public String getContent() {
30         return content;
31     }
32     public void setContent(String content) {
33         this.content = content;
34     }
35     public EnumInfoType getInfoType() {
36         return infoType;
37     }
38     public void setInfoType(EnumInfoType infoType) {
39         this.infoType = infoType;
40     }
41     public Info(String fromUser, String toUser, String sendTime, String content, EnumInfoType infoType) {
42         super();
43         this.fromUser = fromUser;
44         this.toUser = toUser;
45 
46         this.content = content;
47         this.infoType = infoType;
48     }
49     @Override
50     public String toString() {
51         return "Info [fromUser=" + fromUser + ", toUser=" + toUser  + ", content=" + content
52                 + ", infoType=" + infoType + "]";
53     }
54     public Info() {
55         super();
56     }
57     
58 }
Info
 1 package com.gh.model;
 2 
 3 import java.io.Serializable;
 4 
 5 @SuppressWarnings("serial")
 6 public class LoginInfo implements Serializable{
 7     private String name;
 8     private String pwd;
 9     private boolean flag=false;
10     public String getName() {
11         return name;
12     }
13     public void setName(String name) {
14         this.name = name;
15     }
16     public String getPwd() {
17         return pwd;
18     }
19     public void setPwd(String pwd) {
20         this.pwd = pwd;
21     }
22     public boolean isFlag() {
23         return flag;
24     }
25     public void setFlag(boolean flag) {
26         this.flag = flag;
27     }
28     public LoginInfo(String name, String pwd) {
29         super();
30         this.name = name;
31         this.pwd = pwd;
32     }
33     public LoginInfo() {
34         super();
35     }
36     @Override
37     public String toString() {
38         return "LoginInfo [name=" + name + ", pwd=" + pwd + ", flag=" + flag + "]";
39     }
40     
41 }
LoginInfo
 1 package com.gh.model;
 2 /**
 3  * 用户模型
 4  * @author ganhang
 5  * 暂时没用,因为没涉及数据库和一些用户管理功能
 6  */
 7 public class User {
 8     private String name;
 9     private String age;
10     private String pwd;
11     private String email;
12     public String getName() {
13         return name;
14     }
15     public void setName(String name) {
16         this.name = name;
17     }
18     public String getAge() {
19         return age;
20     }
21     public void setAge(String age) {
22         this.age = age;
23     }
24     public String getPwd() {
25         return pwd;
26     }
27     public void setPwd(String pwd) {
28         this.pwd = pwd;
29     }
30     public String getEmail() {
31         return email;
32     }
33     public void setEmail(String email) {
34         this.email = email;
35     }
36     @Override
37     public String toString() {
38         return "User [name=" + name + ", age=" + age + ", pwd=" + pwd + ", email=" + email + "]";
39     }
40     public User(String name, String age, String pwd, String email) {
41         super();
42         this.name = name;
43         this.age = age;
44         this.pwd = pwd;
45         this.email = email;
46     }
47     public User() {
48         super();
49     }
50     public User(String name, String pwd) {
51         super();
52         this.name = name;
53         this.pwd = pwd;
54     }
55     public User(String name) {
56         super();
57         this.name = name;
58     }
59     
60 }
User

 整个代码:https://github.com/ganhang/My-ChatSystem

posted @ 2016-01-27 23:17  CodeNoob  阅读(13330)  评论(1编辑  收藏  举报