項目總結:此次項目主要是根據視頻來的,結果跟到一半感受跟不上,慢慢本身有了本身的想法,決定本身先不看學習視頻,本身先試着寫。java
總結寫前面,算是寫的第一個項目吧。項目中遇到幾點問題,首先Scoket對象建立後,服務器端和客戶端不能同時建立輸入流,否者會引發堵塞。git
而後,讀入流應該從新建立個線程作等待寫入服務,由於讀入流會引發當前線程進入阻塞狀態。github
還有一個用戶線程對應一個服務線程,不是多個用戶線程對應一個服務線程。數據庫
對對象的操做應該由那個對象自己提供操做方法,好比操做UI界面的變化應該由界面自己提拱。服務器
最後最重要的是寫代碼以前應該先畫個流程圖,寫代碼時參數亂傳的,哪裏須要就調參數過來。致使思路不清.app
首先是需求分析:ide
本次項目是模擬及時通訊中最基本的功能,相似QQ的應用.模塊化
項目分爲:學習
(1)服務器端:this
服務器端主要負責用戶管理,消息轉發功能
(2) 客戶端:
客戶端主要負責用戶間的消息發送
詳細設計
服務器端
一、登陸服務器後,進行客戶端的監聽,若有客戶端鏈接,啓動用戶服務線程,與客戶端進行交互。
二、如客戶端向全部人發送消息,服務器將向全部在線用戶廣播該消息。
三、如客戶端向指定人發送消息,服務器將查找接收人用戶線程後轉發消息。
四、用戶登陸後,向全部人更新用戶列表。
客戶端:
一、用戶登陸功能。
二、登陸後用戶能夠看到在線用戶列表
3 、向指定人發送消息
四、向全部人發送消息
代碼的實現
首先,先構建界面圖形出來
上面左邊是用戶界面(服務器界面和用戶界面同樣),右邊是登陸界面
因爲全用手寫代碼比較麻煩,我用了可視化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 }
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 }
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 }
服務端代碼
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 }
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 }
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 }
對象模型
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 }
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 }
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 }
整個代碼:https://github.com/ganhang/My-ChatSystem