|
@@ -1,5 +1,11 @@
|
|
|
-using Microsoft.AspNetCore.SignalR;
|
|
|
+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
|
|
@@ -7,62 +13,119 @@ namespace IES.ExamServer.DI.SignalRHost
|
|
|
public class SignalRExamServerHub : Hub<IClient>
|
|
|
{
|
|
|
private readonly ILogger<SignalRExamServerHub> _logger;
|
|
|
+ private readonly IMemoryCache _memoryCache;
|
|
|
|
|
|
- public SignalRExamServerHub(ILogger<SignalRExamServerHub> logger)
|
|
|
+ public SignalRExamServerHub(ILogger<SignalRExamServerHub> logger,IMemoryCache memoryCache)
|
|
|
{
|
|
|
_logger = logger;
|
|
|
-
|
|
|
+ _memoryCache = memoryCache;
|
|
|
}
|
|
|
- }
|
|
|
- public interface IClient
|
|
|
- {
|
|
|
- Task ReceiveMessage(MessageBody message);
|
|
|
- Task ReceiveConnection(MessageBody message);
|
|
|
- Task ReceiveDisConnection(MessageBody message);
|
|
|
- }
|
|
|
- public abstract class MessageBody
|
|
|
- {
|
|
|
- public MessageBody()
|
|
|
+
|
|
|
+ // <summary>
|
|
|
+ /// 这需要继承Hub来创建中心,并向中心添加方法,客户端可以调用标识符为public的方法
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="user"></param>
|
|
|
+ /// <param name="message"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+
|
|
|
+ public async Task SendMessage(string clientId, string grant_type, MessageContent content )
|
|
|
{
|
|
|
- time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
+ SignalRClient client = _memoryCache.Get<SignalRClient>($"{Constant._KeySignalRClientClients}:{clientId}");
|
|
|
+ if (client != null)
|
|
|
+ {
|
|
|
+ switch (true)
|
|
|
+ {
|
|
|
+ case bool when grant_type.Equals(Constant._Message_grant_type_check_file):
|
|
|
+ {
|
|
|
+ await Clients.Client(client.connid!).ReceiveMessage(new CheckFileMessageBody
|
|
|
+ {
|
|
|
+ content = content.content,
|
|
|
+ status = content.status,
|
|
|
+ clientid = clientId,
|
|
|
+ connid = client.connid,
|
|
|
+ grant_type = grant_type,
|
|
|
+ time = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
|
|
|
+ type = Constant._Message_grant_type_check_file,
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
/// <summary>
|
|
|
- /// 连接id
|
|
|
- /// </summary>
|
|
|
- public virtual string? connid { get; set; }
|
|
|
- /// <summary>
|
|
|
- /// 客户端id
|
|
|
- /// </summary>
|
|
|
- public virtual string? clientid { get; set; }
|
|
|
- /// <summary>
|
|
|
- /// 状态 busy 忙碌,free 空闲,down 离线,error 错误
|
|
|
- /// </summary>
|
|
|
- public virtual string? status { get; set; }
|
|
|
- /// <summary>
|
|
|
- /// 消息内容
|
|
|
- /// </summary>
|
|
|
- public virtual string? content { get; set; }
|
|
|
- /// <summary>
|
|
|
- /// 消息创建时间
|
|
|
- /// </summary>
|
|
|
- public virtual long time { get; }
|
|
|
- /// <summary>
|
|
|
- /// 授权类型,bookjs_api
|
|
|
- /// </summary>
|
|
|
- public virtual string? grant_type { get; set; }
|
|
|
- /// <summary>
|
|
|
- /// 消息类型
|
|
|
+ /// 客户连接成功时触发
|
|
|
/// </summary>
|
|
|
- public virtual MessageType message_type { get; set; }
|
|
|
-
|
|
|
+ /// <returns></returns>
|
|
|
+ public override async Task OnConnectedAsync()
|
|
|
+ {
|
|
|
+ ServerDevice device = _memoryCache.Get<ServerDevice>(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}:{Constant._Message_grant_type_check_file}:{clientid}", JsonSerializer.Serialize(client));
|
|
|
+ _memoryCache.Set($"{Constant._KeySignalRClientConnects}:{Constant._Message_grant_type_check_file}:{connid}", JsonSerializer.Serialize(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<SignalRClient>($"{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 enum MessageType
|
|
|
+ public interface IClient
|
|
|
{
|
|
|
- conn_success,//连接成功
|
|
|
- conn_error,// 连接失败
|
|
|
- task_send_success,// 任务发送成功
|
|
|
- task_send_error,// 任务发送失败
|
|
|
- task_execute_success,// 任务执行成功
|
|
|
- task_execute_error,// 任务执行失败
|
|
|
+ Task ReceiveMessage(MessageBody message);
|
|
|
+ Task ReceiveConnection(MessageBody message);
|
|
|
+ Task ReceiveDisConnection(MessageBody message);
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
}
|