
(附源码)vue3.0+.NET6实现聊天室(实时聊天SignalR)
(纯手写)基于Vue3.0+vite+.net6+SignalR等技术开发实现的网页端聊天实例项目Aerwen/Chat。实现了发送图文表情消息/gif图、emjoi表情、图片、网址查看、下拉刷新,群聊,好友发送消息...功能等功能。
可以注册两个号来测试
演示图:
一. 整体介绍
介绍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)
下图是我在渲染聊天列表时做的判断:
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 来判断这个群聊是否为指定的群
更多推荐
所有评论(0)