JAVA入門到精通-第92講-山寨QQ項目6-多對多的聊天
阿新 • • 發佈:2018-12-01
不同的 llc data- cli 界面 shm tool 出現 per QQ聊天項目演示-多對多的聊天流同時並發的異常;
服務器中轉2/3號只有一個連接;
接收信息:while循環不停地讀取;
當1號點開兩個窗口時,2/3會共同去爭取這個socket;會出現流同時並發異常;
Socket處理成static不太合理;
啟動一個窗口就會占據Socket不放;
--------------實現真正的多人聊天,互相不出現錯誤-每一個登錄的賬號獨享一份socket-去掉static當一個鏈接達成的時候,啟動線程,和服務器保持通訊的狀態;做一個類來管理客戶端這邊的線程;
-新的賬號登錄,開一個線程ClientConServerThread
-管理線程的類,放入到一個HashMap裏面:ManageClientConServerThread;
HashMap<k,v>k:用戶賬號,某個賬號獨享的線程v:ClientConServerThread
------------------當賬號登錄成功,創建線程,把線程放入HashMap
--------------------Qq聊天界面沒有必要成為一個線程;本身是不合理的;
通過 管理線程的類,取得了線程,通過線程取得socket,通過socket,取得了輸出流:getOutputStream;
----------------------給每一個登錄賬號分配線程;把通訊的任務交給線程類;---------------------
-多對多聊天經測試,後臺發送消息正常;
----------------顯示後臺的消息到各自的聊天界面
110110 1
來自為知筆記(Wiz)
服務器中轉2/3號只有一個連接;
接收信息:while循環不停地讀取;
當1號點開兩個窗口時,2/3會共同去爭取這個socket;會出現流同時並發異常;
Socket處理成static不太合理;
啟動一個窗口就會占據Socket不放;
--------------實現真正的多人聊天,互相不出現錯誤-每一個登錄的賬號獨享一份socket-去掉static當一個鏈接達成的時候,啟動線程,和服務器保持通訊的狀態;做一個類來管理客戶端這邊的線程;
-新的賬號登錄,開一個線程ClientConServerThread
-管理線程的類,放入到一個HashMap裏面:ManageClientConServerThread;
HashMap<k,v>k:用戶賬號,某個賬號獨享的線程v:ClientConServerThread
------------------當賬號登錄成功,創建線程,把線程放入HashMap
--------------------Qq聊天界面沒有必要成為一個線程;本身是不合理的;
通過 管理線程的類,取得了線程,通過線程取得socket,通過socket,取得了輸出流:getOutputStream;
----------------------給每一個登錄賬號分配線程;把通訊的任務交給線程類;---------------------
-多對多聊天經測試,後臺發送消息正常;
----------------顯示後臺的消息到各自的聊天界面
QqChat.java]
/**
2 * 這是與好友聊天的界面
3 * 因為客戶端,要處於讀取的狀態,因此我們把它做成一個線程
4 */
5package com.qq.client.view;
6
7import java.awt.event.ActionEvent;
8import java.awt.event.ActionListener;
9import java.io.IOException;
10import java.io.ObjectInputStream;
11import java.io.ObjectOutputStream;
12import java.util.Date;
13import javax.swing.ImageIcon;
14import javax.swing.JButton;
15import javax.swing.JFrame;
16import javax.swing.JPanel;
17import javax.swing.JScrollPane;
18import javax.swing.JTextArea;
19import javax.swing.JTextField;
20import com.qq.client.model.QqClientConServer;
21import com.qq.client.tools.ManageClientConServerThread;
22import com.qq.common.Message;
23import com.qq.common.MessageType;
24
25public class QqChat extends JFrame implements ActionListener {
26 JTextArea jta;
27 JTextField jtf;
28 JButton jb;
29 JPanel jp;
30 JScrollPane jsp;
31 String ownerId;
32 String friendId;
33
34 // public static void main(String[] args) {
35 // new QqChat("小四");
36 // }
37
38 // 構造函數
39 public QqChat(String friendId, String ownerId) {
40 this.ownerId = ownerId;
41 this.friendId = friendId;
42
43 jta = new JTextArea();
44 jtf = new JTextField(15);
45 jb = new JButton("發送");
46 jb.addActionListener(this);
47 jp = new JPanel();
48 jp.add(jtf);
49 jp.add(jb);
50 jsp = new JScrollPane(jta);
51
52 this.add(jsp, "Center");
53 this.add(jp, "South");
54
55 this.setTitle(ownerId + " 正在與 " + friendId + " 聊天");
56 this.setSize(350, 300);
57 this.setIconImage((new ImageIcon("image/qie.jpg")).getImage());
58 this.setLocationRelativeTo(null);
59 this.setVisible(true);
60 }
61
62 // 寫一個方法,讓它顯示消息
63 public void showMessage(Message m){
64 String info=m.getSender()+" 對 "+m.getGetder()+" 說:"+m.getCon()+"\r\n";
65 jta.append(info);
66 }
67
68 @Override
69 public void actionPerformed(ActionEvent e) {
70 if (e.getSource() == jb) {
71 // 如果用戶點擊了發送按鈕
72 Message m = new Message();
73 m.setMesType(MessageType.message_comm_mes);
74 m.setSender(this.ownerId);
75 m.setGetder(this.friendId);
76 m.setCon(this.jtf.getText());
77 m.setSendTime(new Date().toString());
78 jta.append(ownerId + " 對 " + friendId + " 說:" + jtf.getText()
79 + "\r\n");
80 jtf.setText("");
81 // 發送給服務器
82 try {
83 ObjectOutputStream oos = new ObjectOutputStream(
84 ManageClientConServerThread
85 .getClientConServerThread(ownerId).getS()
86 .getOutputStream());
87 oos.writeObject(m);
88 } catch (Exception e1) {
89 e1.printStackTrace();
90 }
91 }
92 }
93
94 // @Override
95 // public void run() {
96 // while(true){
97 // //讀取[如果讀不到就等待]
98 // try {
99 // ObjectInputStream ois=new
100 // ObjectInputStream(QqClientConServer.s.getInputStream());
101 // Message m=(Message)ois.readObject();
102 // //顯示出來
103 // String info=m.getSender()+" 對 "+m.getGetder()+" 說:"+m.getCon()+"\r\n";
104 // jta.append(info);
105 // } catch (Exception e) {
106 // e.printStackTrace();
107 // }
108 // }
109 // }
110}
*******************************************************************************
com.qq.client.model
[QqClienConServer.java]
5454 1/**
2 * 這是客戶端連接服務器的後臺
3 * 功能:客戶端與服務器進行數據交互
4 */
5package com.qq.client.model;
6
7import java.io.ObjectInputStream;
8import java.io.ObjectOutputStream;
9import java.net.Socket;
10import com.qq.client.tools.ClientConServerThread;
11import com.qq.client.tools.ManageClientConServerThread;
12import com.qq.common.Message;
13import com.qq.common.User;
14
15public class QqClientConServer {
16 public Socket s;
17
18 //發送第一次請求
19 public boolean sendLoginInfoToServer(Object o){
20 boolean b=false;
21
22 try {
23 s=new Socket("127.0.0.1",9999);
24 ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
25 oos.writeObject(o);
26
27 ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
28 Message ms=(Message)ois.readObject();
29 //這裏就是驗證用戶登錄的地方
30 if(ms.getMesType().equals("1")){
31 b=true;
32 //就創建一個該qq號和服務器端保持通訊連接的線程
33 ClientConServerThread ccst=new ClientConServerThread(s);
34 //啟動該通訊線程
35 ccst.start();
36
37 ManageClientConServerThread.addClientConServerThread(((User)o).getUserId(), ccst);
38 }
39 } catch (Exception e) {
40 e.printStackTrace();
41 } finally{
42 }
43 return b;
44 }
45
46 //向服務器發送一個對象
47 public void SendInfoToServer(Object o){
48 try {
49 Socket s=new Socket("127.0.0.1",9999);
50 } catch (Exception e) {
51 e.printStackTrace();
52 } finally{
53 }
54 }
}
*******************************************************************************
[QqClientUser.java]
1515 1/**
2 * 用戶操作邏輯類
3 * QqClientUser會調用QqClientConServer的
4 * 方法sendLoginInfoToServer向服務器發送
5 */
6package com.qq.client.model;
7
8import com.qq.common.User;
9
10public class QqClientUser {
11 //驗證用戶是否合法
12 public boolean checkUser(User u){
13 return new QqClientConServer().sendLoginInfoToServer(u);
14 }
15}
*******************************************************************************
com.qq.client.tools
[ClientConServerThread.java]
5858 1/**
2 * 這是客戶端和服務器端保持通訊的線程
3 */
4package com.qq.client.tools;
5
6import java.io.ObjectInputStream;
7import java.net.Socket;
8import com.qq.client.view.QqChat;
9import com.qq.client.view.QqFriendList;
10import com.qq.common.Message;
11import com.qq.common.MessageType;
12
13public class ClientConServerThread extends Thread{
14 private Socket s;
15
16 public Socket getS() {
17 return s;
18 }
19
20 public void setS(Socket s) {
21 this.s = s;
22 }
23
24 //構造函數
25 public ClientConServerThread(Socket s){
26 this.s=s;
27 }
28
29 public void run(){
30 while(true){
31 //不停的讀取從服務器端發來的消息
32 try {
33 ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
34 Message m=(Message)ois.readObject();
35
36 //按消息包的類型來處理不同的包
37 if(m.getMesType().equals(MessageType.message_comm_mes)){
38 //把從服務器獲得的消息,顯示到該顯示的聊天界面上
39 QqChat qqChat=ManageQqChat.getQqChat(m.getGetder()+" "+m.getSender());
40 //顯示
41 qqChat.showMessage(m);
42 }else if(m.getMesType().equals(MessageType.message_ret_onLineFriend)){
43 String con=m.getCon();
44 String []friends=con.split(" ");
45 String getter=m.getGetder();
46 //修改相應的好友列表
47 QqFriendList qqFrindList=ManageQqFriendList.getQqFriendList(getter);
48 //更新在線好友
49 if(qqFrindList!=null){
50 qqFrindList.updateFriend(m);
51 }
52 }
53 } catch (Exception e) {
54 e.printStackTrace();
55 }
56 }
57 }
58}
*******************************************************************************
[ManageClientConServerThread.java]
x1
/**
2 * 這是一個管理客戶端與服務器保持通訊的線程類
3 */
4package com.qq.client.tools;
5
6import java.util.HashMap;
7
8public class ManageClientConServerThread {
9 private static HashMap hm=new HashMap<String, ClientConServerThread>();
10 //把創建好的ClientConServerThread放入到hm中
11 public static void addClientConServerThread(String qqId,ClientConServerThread ccst){
12 hm.put(qqId, ccst);
13 }
14
15 //可以通過qqId取得該線程
16 public static ClientConServerThread getClientConServerThread(String qqId){
17 return (ClientConServerThread)hm.get(qqId);
18 }
19}
20
來自為知筆記(Wiz)
JAVA入門到精通-第92講-山寨QQ項目6-多對多的聊天