參考文章
搭建文章
gitte源碼
線上體驗
可以注冊兩個号來測試
示範圖:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5CNmFWZyEjYmBDMkZjZzkjZ0MWN3IzNldjNzATOhBjZh9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.gif)
一. 整體介紹
介紹SignalR一種通訊模型Hub(中心模型,或者叫集線器模型),調用這個模型寫好的方法,去發送消息。
内容有:
①:Hub模型的方法介紹
②:伺服器端代碼介紹
③:前端vue3 安裝并調用後端方法
④:聊天室樣例
整體流程:
1、進入網站 -> 調用連接配接 SignalR 的方法
2、與好友發送消息 -> 調用 SignalR 的自定義方法
前端通過,signalR内置方法 .invoke() 去請求接口
3、監聽接受方法(渲染消息)
通過 new signalR.HubConnectionBuilder().on("接受方法") 這個函數
然後将接受的消息 存放到數組裡
再 v-for 将資料渲染出來
4、退出浏覽器或登出,觸發 “連接配接終止時調用” (OnDisconnectedAsync)
修改登入狀态為 離線
/// <summary>
/// 連接配接終止時調用。
/// </summary>
/// <returns></returns>
public override Task OnDisconnectedAsync(Exception? exception)
{
var httpContext = Context.GetHttpContext();
var username = httpContext.Request.Cookies["username"];
if (username == null)
{
throw new Exception("系統異常連接配接失敗");
}
// 修改使用者登入狀态
_ChatLoginService.Update(s => s.ChatUserName == username,
f => new ChatUser
{
Status = 0
});
var user = clientusers.Where(p => p.ConnectionId == Context.ConnectionId).FirstOrDefault();
判斷使用者是否存在,否則添加集合
if (user != null)
{
clientusers.Remove(user);
}
return base.OnDisconnectedAsync(exception);
}
在檔案夾 ARW-vue-main\src\views\tool\chat 中的 index.vue 是簡易版的demo
可以先把這個搞明白,後面會很好了解
這個對應的Hub 是 MessageHub
二. Hub模型的方法介紹
繼承成Hub類,是以可以Override三個方法:
(1). OnConnected:連接配接成功時調用
(2). OnDisconnected:連接配接斷開時調用
(3). OnReconnected:重連時調用
我這裡用于 修改使用者登入狀态 線上人數清單...
使用Clients對象進行調用,Clients對象下的屬性和方法有:
(1). 向指定人發送,一對一:Client(string connectionId)
(2). 向某個組發送:Group(roomName)
(3). 進入某個房間:Group.AddToGroupAsync(connectId, roomName)
三. 伺服器端代碼介紹
好友聊天思路詳細講解:
/// <summary>
/// 好友發送資訊
/// </summary>
/// <param name="user"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task SendFriendsChat(string selfConnectionId, string connectId, string sender, string receiver, string message)
{
if (string.IsNullOrEmpty(connectId))
{
throw new CustomException("好友不線上,請留言!");
}
// 服務端主動調用用戶端的方法
// 向指定使用者(connectId)發送指定消息
// 監聽接受方法("ReceiveMessage")來擷取消息 -> ( new { sender, receiver, message } )
await Clients.Client(connectId).SendAsync("ReceiveMessage", new { sender, receiver, message });
await Clients.Client(selfConnectionId).SendAsync("ReceiveMessage", new { sender, receiver, message });
}
我們直接手撕源碼,先看這個方法的參數 一共有5個
參數說明: connectId-> 在連接配接SignalR時會給該使用者生成一個連接配接Id,并存在線上使用者清單裡
後面統稱 "連接配接ID"
1、selfConnectionId -> 自己的連接配接ID
2、connectId -> 對方的連接配接ID
3、sender -> 發送者的使用者GUID
4、receiver-> 接收者的使用者GUID
5、message -> 發送的消息
首先我們給發送消息,必須先知道對方的 connectId
才能夠調用 Clients.Client(connectId).SendAsync(.......)
Q:為什麼需要自己的連接配接ID呢?
A:因為給對方發送,對方能夠接收到消息,但自己是接收不到的,是以這裡要給自己也發一份。因而需要傳自己的連接配接ID。
Q:如何區分是誰發送的消息?
A:這裡我用的是 接收者 和 發送者 做的判斷,這裡需要捋一捋思路,是以這裡要傳發送者的GuId 和 接收者的GuId。(發送消息時也帶 sender 和 recevier)
下圖是我在渲染聊天清單時做的判斷:![]()
(附源碼)vue3.0+.NET6實作聊天室(實時聊天SignalR) ![]()
(附源碼)vue3.0+.NET6實作聊天室(實時聊天SignalR) Q:如果好友不線上,擷取不到對方的連接配接ID怎麼辦?
A:這個情況再去請求Hub接口是會報錯的,因為對方的連接配接Id是空的。我的做法是每次發送一條消息就會存進資料庫裡嘛,然後判斷一下對方是否線上,不線上就擷取他們之間的對話的最新一條消息,這裡sql比較複雜,感興趣的可以看看這個。
看懂這個方法後,來看一下 前端調用
基礎使用
對前端感興趣的可以看一下源碼
群聊聊天思路詳解:
/// <summary>
/// 進入指定組
/// </summary>
/// <param name="connectId"></param>
/// <param name="roomName">組的名稱</param>
[HubMethodName(nameof(EnterRoom))]
public void EnterRoom(string connectId, string roomName)
{
Groups.AddToGroupAsync(connectId, roomName);
}
/// <summary>
/// 群聊天(發送資訊)
/// </summary>
/// <param name="roomName"></param>
public async Task SendGroupChat(string roomName, string groupGuId, string selfConnectionId, string senderId, string receiver, string message)
{
var guid = senderId.ParseToLong();
var groupguid = groupGuId.ParseToLong();
var sender = _ChatLoginService.FindUserByGuid(guid).Result;
await Clients.Group(roomName)
.SendAsync("groupMessages", new { roomName, sender, receiver, message });
_GroupUserService.Update(s => s.GroupGuId == groupguid,
f => new GroupUser
{
IsRead = false
});
//await Clients.Client(selfConnectionId).SendAsync("groupMessages", new { sender, receiver, message });
}
}
我們繼續手撕源碼,先看這個方法的參數 一共有6個
參數說明: roomName -> 在SignalR中組名,如果沒有這個組名則添加并進入清單,有則加入組
後面統稱 "組"
1、roomName -> 組名
2、groupGuId -> 群聊的GUID
3、selfConnectionId -> 自己的連接配接ID
4、senderId -> 發送者的使用者GUID
5、receiver-> 接收者的GUID(這裡指群聊的GUID)
6、message -> 發送的消息
Clients.Group(roomName).SendAsync("接受方法名",發送的消息)
首先要 進入到房間内:
把自己的連接配接ID放進去,以及群聊名稱
Groups.AddToGroupAsync(connectId, roomName);
在群聊發送消息,需要做到:
1、通過 roomName 發送消息到這個房間
2、通過 groupGuId 來修改使用者是否已讀
3、通過 senderId 來判斷是否自己發的,不是則展示群成員發的頭像和所發的消息
4、通過 receiver 來判斷這個群聊是否為指定的群