多用戶即時通訊系統04 4.編碼實現03 4.5功能實現-群聊功能實現 4.5.1思路分析 群聊的實現思路和私聊的實現非常類似。 不同的是:私聊時,服務端接收到消息後,只需要找出接收方的socket併發送消息即可 群聊時,服務端在接收到消息後需要遍歷集合中所有的線程,找出除了發送方的所有客戶端的so ...
多用戶即時通訊系統04
4.編碼實現03
4.5功能實現-群聊功能實現
4.5.1思路分析
群聊的實現思路和私聊的實現非常類似。
不同的是:私聊時,服務端接收到消息後,只需要找出接收方的socket併發送消息即可
群聊時,服務端在接收到消息後需要遍歷集合中所有的線程,找出除了發送方的所有客戶端的socket,併發送消息
群聊思路:
- 客戶端 - 發送者:
- 用戶在控制台輸入信息,客戶端接收內容
- 將消息構建成Messgae對象,通過對應的socket發送給伺服器
- 伺服器:
- 讀取客戶端(發送者)發送給所有用戶(接收者)的消息
- 從管理線程的集合中,遍歷所有線程,獲取所有socket(除了發送者本身)
- 將Message對象轉發給所有的接收者
- 客戶端 - 所有接收者:
- 所有接受者分別線上程(通信線程)中,讀取到發送者的message消息,並顯示即可
4.5.2代碼實現
1.客戶端:
1.修改MessageType介面
在介面中增加新的消息類型
String MESSAGE_TO_ALL_MES = "7";//表示群發消息包
2.修改MessageClientService類
在該類中增加sendMessageToAll方法,實現群發功能
/**
* 群發消息功能
* @param content 內容
* @param senderId 發送者
*/
public void sendMessageToAll(String content,String senderId){
//構建 message
Message message = new Message();
message.setMesType(MessageType.MESSAGE_TO_ALL_MES);//設置消息類型是群發消息
message.setSender(senderId);
message.setContent(content);
message.setSendTime(new Date().toString());//發送時間也封裝到 message對象中
System.out.println(senderId + " 對大家說 " + content);
//發送給服務端
try {//在管理線程的集合中,通過userId來獲取線程,通過線程來獲取對應的socket,再通過socket獲取輸出流
ObjectOutputStream oos =
new ObjectOutputStream(ManageClientConnectServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());
oos.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
3.修改ClientConnectServerThread類
在該類的run方法中增加新的邏輯業務,增加接收群發消息類型的判斷,併在控制台顯示
else if (message.getMesType().equals(MessageType.MESSAGE_TO_ALL_MES)) {
//接收到的是群發的消息
//就把伺服器轉發的消息,顯示到控制台即可
System.out.println("\n" + message.getSendTime() + "\n" + message.getSender()
+ " 對大家說: " + "\n" + message.getContent());
}
4.修改QQView類
在該類的內層迴圈中,調用群發功能的方法:
case "2":
System.out.println("請輸入想對大家說的話");
String s = Utility.readString(100);
//調用一個方法,將消息封裝成 message對象,發給服務端
messageClientService.sendMessageToAll(s,userId);
break;
2.服務端:
1.修改MessageType介面
在介面中增加新的消息類型
String MESSAGE_TO_ALL_MES = "7";//表示群發消息包
2.修改ServerConnectClientThread類
在該類中增加新的業務邏輯
else if (message.getMesType().equals(MessageType.MESSAGE_TO_ALL_MES)) {
//業務四:客戶請求群發消息需要遍歷管理線程的集合,把所有線程的socket都得到,然後將 message進行轉發即可
//得到hm
HashMap<String, ServerConnectClientThread> hm = ManageClientThreads.getHm();
//遍歷
Iterator<String> iterator = hm.keySet().iterator();
while (iterator.hasNext()) {
//取出所有userId
String onlineUserId = iterator.next().toString();
//取出除了發送者的所有用戶id
if (!onlineUserId.equals(message.getSender())) {
//轉發message
//從集合中取出線程,線上程中取出socket,根據socket獲得輸出流,將socket的輸出流轉化為對象輸出流
ObjectOutputStream oos =
new ObjectOutputStream(hm.get(onlineUserId).getSocket().getOutputStream());
oos.writeObject(message);
}
}
}
3.修改ManageClientThreads類
在該類中增加方法,獲取集合
//返回hashmap
public static HashMap<String ,ServerConnectClientThread> getHm(){
return hm;
}
運行程式:
1.運行服務端,進行監聽
2.運行三個客戶端,登錄三個用戶
3.在 用戶uid=100 的賬號發送群發消息
4.其他用戶也接收到了消息
5.伺服器端
功能實現完畢