Admin.Net中的消息通信SignalR解释

定义集线器接口

IOnlineUserHub

csharp 复制代码
public interface IOnlineUserHub
{
    /// 在线用户列表
    Task OnlineUserList(OnlineUserList context);

    /// 强制下线
    Task ForceOffline(object context);

    /// 发布站内消息
    Task PublicNotice(SysNotice context);

    /// 接收消息
    Task ReceiveMessage(object context);
}

实现集线器

OnlineUserHub

csharp 复制代码
/// <summary>
/// 在线用户集线器
/// </summary>
[MapHub("/hubs/onlineUser")]
public class OnlineUserHub : Hub<IOnlineUserHub>
{
    private readonly IHubContext<OnlineUserHub, IOnlineUserHub> _hub;
    public OnlineUserHub(...,
        IHubContext<OnlineUserHub, IOnlineUserHub> hub)
    {
        ...
        // 注入 Hub
        _hub = hub;
    }
    
	// 有客户端通过SignalR连接过来, 把连接信息保存到数据库
	public override async Task OnConnectedAsync()
	{
	...... // 业务代码

       var user = new SysOnlineUser
       {
           ConnectionId = Context.ConnectionId,
           UserId = userId,
           UserName = account,
           RealName = realName,
           Time = DateTime.Now,
           Ip = httpContext.GetRemoteIpAddressToIPv4(true),
           TenantId = tenantId,
       };
       await _sysOnlineUerRep.InsertAsync(user); // 保存当前登录用户到数据库

       // 制作分组
       var groupName = $"{GROUP_ONLINE}{user.TenantId}";
       await this.Groups.AddToGroupAsync(Context.ConnectionId, groupName);
	    
	    // 推送消息给前端, 推送给一个分组
	    await this.Clients.Groups(groupName).OnlineUserList(new OnlineUserList
	    {
	        RealName = user.RealName,
	        Online = true,
	        ...
	    });
	}
	
    // 客户端断开了
    public override async Task OnDisconnectedAsync(Exception exception)
    { ... }

	// 自定义方法
	public async Task ForceUserOffline()
	{
	    ...... // 业务代码
	    
	    // 推送消息给前端, 推送给指定的人
	    await _hub.Clients.Client(input.ConnectionId).ForceOffline("强制下线");
	}
}

前端监听消息

js 复制代码
import { signalR } from './signalR';

onMounted(async () => {
	signalR.off('ForceOffline');// 关闭监听
	// 开始监听, 编写回调
	signalR.on('ForceOffline', async (data: any) => {
		// 收到这个消息, 把当前用户下线
		// 停止接收消息
		await signalR.stop(); 
		
		// 告诉后端我下线了( 根据业务需要, 可以不用)
		await getAPI(SysAuthApi).apiSysAuthLogoutPost();
		// 清空本地Token (下线)
		clearAccessTokens();
	});
});

前端SignalR配置

signalR.ts

ts 复制代码
import * as SignalR from '@microsoft/signalr';
import { ElNotification } from 'element-plus';
import { getToken } from '/@/utils/axios-utils';

// 初始化SignalR对象
const connection = new SignalR.HubConnectionBuilder()
	.configureLogging(SignalR.LogLevel.Information)
	.withUrl(`${window.__env__.VITE_API_URL}/hubs/onlineUser?token=${getToken()}`, { transport: SignalR.HttpTransportType.WebSockets, skipNegotiation: true })
	.withAutomaticReconnect({
		nextRetryDelayInMilliseconds: () => {
			return 5000; // 每5秒重连一次
		},
	})
	.build();

connection.keepAliveIntervalInMilliseconds = 15 * 1000; // 心跳检测15s
connection.serverTimeoutInMilliseconds = 30 * 60 * 1000; // 超时时间30m

// 启动连接
connection.start().then(() => {
	console.log('启动连接');
});
// 断开连接
connection.onclose(async () => {
	console.log('断开连接');
});
// 重连中
connection.onreconnecting(() => {
	ElNotification({
		title: '提示',
		message: '服务器已断线...',
		type: 'error',
		position: 'bottom-right',
	});
});
// 重连成功
connection.onreconnected(() => {
	console.log('重连成功');
});

connection.on('OnlineUserList', () => {});

export { connection as signalR };
相关推荐
csdn_aspnet2 个月前
使用 SignalR 在 .NET Core 8 最小 API 中构建实时通知
signalr·.net8
csdn_aspnet2 个月前
在 .NET 8 中使用自定义令牌身份验证掌握 SignalR Hub 安全性
signalr·.net8
lixww.cn4 个月前
ASP.NET Core SignalR向部分客户端发消息
javascript·websocket·vue·asp.net core·signalr
lixww.cn4 个月前
ASP.NET Core SignalR的协议协商
asp.net core·signalr
lixww.cn4 个月前
ASP.NET Core SignalR的分布式部署
redis·消息队列·asp.net core·signalr
三天不学习6 个月前
ASP.NET Core SignalR 双工通信
后端·asp.net·signalr·websockets·双工通信
敲厉害的燕宝9 个月前
SignalR——聊天室实践
前端·javascript·html·signalr
lee57610 个月前
.net 8.0 下 Blazor 通过 SignalR 与 Winform 交互
blazor·signalr
武穆逸仙1 年前
如何在.NET中集成SignalR
.net·signalr