using IES.ExamServer.Helper; using IES.ExamServer.Models; using IES.ExamServer.Services; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; using System.Text.Json; namespace IES.ExamServer.DI.SignalRHost { public static class SignalRExamServerHubExtension { public async static Task SendMessage(this IHubContext hubContext, IMemoryCache _memoryCache, ILogger logger, string clientId, string grant_type, MessageContent content,bool isLog=false) { try { //双向检测是否连接。 SignalRClient signalRClient = _memoryCache.Get($"{Constant._KeySignalRClientClients}:{clientId}"); if (signalRClient!=null) { signalRClient = _memoryCache.Get($"{Constant._KeySignalRClientConnects}:{signalRClient.connid}"); } int code = 0; string msg = ""; CheckFileMessageBody messageBody = new CheckFileMessageBody { content = content.content, status = content.status, clientid = clientId, connid = signalRClient?.connid, grant_type = grant_type, time = DateTimeOffset.Now.ToUnixTimeMilliseconds(), type = Constant._Message_type_message, contents = content.contents, step=content.step, finish = content.finish }; if (signalRClient != null) { try { switch (true) { case bool when grant_type.Equals(Constant._Message_grant_type_ies_qrcode_login): { await hubContext.Clients.Client(signalRClient.connid!).SendAsync("ReceiveMessage", messageBody); code=200; msg = $"发送成功"; break; } case bool when grant_type.Equals(Constant._Message_grant_type_download_file): { await hubContext.Clients.Client(signalRClient.connid!).SendAsync("ReceiveMessage", messageBody); code=200; msg = $"发送成功"; break; } case bool when grant_type.Equals(Constant._Message_grant_type_check_file): { await hubContext.Clients.Client(signalRClient.connid!).SendAsync("ReceiveMessage", messageBody); code=200; msg = $"发送成功"; break; } default: break; } } catch (Exception ex) { code=500; msg = $"{ex.Message},{ex.StackTrace}"; } } else { code= 400; msg="未连接客户端"; } if (isLog) { logger.LogData(new { code, msg, data = messageBody }, content.dataId!); } } catch (Exception ex) { logger.LogError(ex.Message, ex.StackTrace); } } } public class SignalRExamServerHub : Hub { private readonly ILogger _logger; private readonly IMemoryCache _memoryCache; public SignalRExamServerHub(ILogger logger,IMemoryCache memoryCache) { _logger = logger; _memoryCache = memoryCache; } // /// 这需要继承Hub来创建中心,并向中心添加方法,客户端可以调用标识符为public的方法 /// /// /// /// public void ReceiveMessage(string clientId, string grant_type, string contentmsg ) { _logger.LogInformation($"收到客户端的消息{contentmsg}"); } /// /// 客户连接成功时触发 /// /// public override async Task OnConnectedAsync() { ServerDevice device = _memoryCache.Get(Constant._KeyServerDevice); var connid = Context.ConnectionId; var httpContext = Context.GetHttpContext(); if (httpContext != null) { //wss://www.winteach.cn/signalr/notify?grant_type=wechat_qrcode&scene=0a75aca57536490ba00fe62e27bb8f6c&id=U2MNiCFNPPuVcw2gUI_gRA //wss://www.winteach.cn/signalr/notify?grant_type=bookjs_api&clientid={clientid}&id=客户端自动生成的 httpContext.Request.Query.TryGetValue("grant_type", out StringValues grant_type); httpContext.Request.Query.TryGetValue("clientid", out StringValues clientid); await Groups.AddToGroupAsync(connid, grant_type!); if (!clientid.Equals(StringValues.Empty) && !grant_type.Equals(StringValues.Empty)) { var client = new SignalRClient { connid = connid, grant_type = grant_type, clientid= clientid,//浏览器生成的客户端设备id serverid=device.deviceId,//服务器设备id }; switch (true) { // 检查文件 case bool when grant_type.Equals(Constant._Message_grant_type_check_file): { _memoryCache.Set($"{Constant._KeySignalRClientClients}:{clientid}", client); _memoryCache.Set($"{Constant._KeySignalRClientConnects}:{connid}", client); await SendConnection(connid, new ConnectionMessageBody { connid=connid, clientid = clientid, grant_type = grant_type, content = $"连接成功", type=Constant._Message_type_message, status = Constant._Message_status_success, time = DateTimeOffset.Now.ToUnixTimeMilliseconds(), }); break; } // 扫码登录 case bool when grant_type.Equals(Constant._Message_grant_type_ies_qrcode_login): { _memoryCache.Set($"{Constant._KeySignalRClientClients}:{clientid}", client); _memoryCache.Set($"{Constant._KeySignalRClientConnects}:{connid}", client); await SendConnection(connid, new ConnectionMessageBody { connid=connid, clientid = clientid, grant_type = grant_type, content = $"连接成功", type=Constant._Message_type_message, status = Constant._Message_status_success, time = DateTimeOffset.Now.ToUnixTimeMilliseconds(), }); break; } // 下载文件 case bool when grant_type.Equals(Constant._Message_grant_type_download_file): { _memoryCache.Set($"{Constant._KeySignalRClientClients}:{clientid}", client); _memoryCache.Set($"{Constant._KeySignalRClientConnects}:{connid}", client); await SendConnection(connid, new ConnectionMessageBody { connid=connid, clientid = clientid, grant_type = grant_type, content = $"连接成功", type=Constant._Message_type_message, status = Constant._Message_status_success, time = DateTimeOffset.Now.ToUnixTimeMilliseconds(), }); break; } // 上传数据 case bool when grant_type.Equals(Constant._Message_grant_type_upload_data): { _memoryCache.Set($"{Constant._KeySignalRClientClients}:{clientid}", client); _memoryCache.Set($"{Constant._KeySignalRClientConnects}:{connid}", client); await SendConnection(connid, new ConnectionMessageBody { connid=connid, clientid = clientid, grant_type = grant_type, content = $"连接成功", type=Constant._Message_type_message, status = Constant._Message_status_success, time = DateTimeOffset.Now.ToUnixTimeMilliseconds(), }); break; } } } } } public async Task SendConnection(string connectionId, ConnectionMessageBody msg) { await Clients.Client(connectionId).ReceiveConnection(msg); } public async override Task OnDisconnectedAsync(Exception? exception) { var connid = Context.ConnectionId; SignalRClient signalRClient = _memoryCache.Get($"{Constant._KeySignalRClientConnects}:{connid}"); if (signalRClient!=null) { _memoryCache.Remove($"{Constant._KeySignalRClientConnects}:{connid}"); _memoryCache.Remove($"{Constant._KeySignalRClientClients}:{signalRClient.clientid}"); await Groups.RemoveFromGroupAsync(connid, signalRClient.grant_type!); } } } public interface IClient { Task ReceiveMessage(MessageBody message); Task ReceiveConnection(MessageBody message); Task ReceiveDisConnection(MessageBody message); } }