1、先按官网来走了一遍
ASP.NET Core SignalR 入门
https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio
试了对所有在线用户发消息,对指定用户发消息等
public class ChatHub : Hub { private static Dictionary<string, string> AllUserDic = new Dictionary<string, string>(); public async Task SendMessage(string user, string reUser, string message) { //与包含自己的所有客户端通讯(收到消息) //await Clients.All.SendAsync("ReceiveMessage", user, message); //与除自己之外的其它客户端通讯(收到消息) //await Clients.Others.SendAsync("ReceiveMessage", user, message); //仅与自己通讯(收消息) //await Clients.Caller.SendAsync("ReceiveMessage", user, message); //if (AllUserDic.ContainsKey(user)) // AllUserDic[user] = Context.ConnectionId; //else // AllUserDic.Add(user, Context.ConnectionId); if (string.IsNullOrEmpty(reUser)) await Clients.Others.SendAsync("ReceiveMessage", user, reUser, message); else { var re = Clients.User(reUser); if (re == null) await Clients.Caller.SendAsync("ReceiveMessage", user, reUser, "消息发送失败"); else await Clients.User(reUser).SendAsync("ReceiveMessage", user, reUser, message); } } }
2、但真实场景中这样操作肯定不行
于是看了好多资料 最简单的就是实现 IUserIdProvider
/// <summary> /// 登陆用户基本信息 /// </summary> public class UserInfo : IUserIdProvider { public string GetUserId(HubConnectionContext connection) { //这里可以重写用户ID,重写后可以直接在Hub的派生类中(ChatHub)直接指定用户ID 推送消息 //var requestContext = connection.GetHttpContext(); //requestContext.Request.Session //requestContext.Request.QueryString["xxx"] //requestContext.Request.Cookies[""] //此处模拟一个用户ID, return Guid.NewGuid().ToString(); } }
public class ChatHub : Hub { /// <summary> /// 发送消息 /// </summary> /// <param name="user">消息发送人(这个只是用来展示 是谁发的而已)</param> /// <param name="reUserId">收消息的人员Id 这里这个ID,就是上面 GetUserId里面重写的值</param> /// <param name="message">消息内容</param> /// <returns></returns> public async Task SendMessage(string user, string reUserId, string message) { //其实user不用传,可以从 Context.User.Claims 或 Context.GetHttpContext() 里面拿到user的所有信息 //此时传入user 只是用来偷懒,因为demo没有做登陆之类的
//如果 没传收消息的人,就发给所有除自己之外的 所有在线的人,反之仅发给指定人 if (string.IsNullOrEmpty(reUserId)) await Clients.Others.SendAsync("ReceiveMessage", user, reUserId, message); else await Clients.User(reUserId).SendAsync("ReceiveMessage", user, reUserId, message); }
public override Task OnConnectedAsync() { var connectionId = Context.ConnectionId; var identityName = Context.User.Identity.Name; return base.OnConnectedAsync(); } public override Task OnDisconnectedAsync(Exception exception) { return base.OnDisconnectedAsync(exception); } }
然后在 Startup.cs里面
//void ConfigureServices(IServiceCollection services)j里面加 services.AddSingleton<IUserIdProvider,UserInfo>(); services.AddSignalR(); //void Configure(IApplicationBuilder app, IHostingEnvironment env)里面不变 app.UseSignalR(routes => { routes.MapHub<ChatHub>("/chatHub"); });
看下结果
当然 现在刷新 页面 这个用户ID就会变,因为一刷新 就会创建新的连接,然后去调用GetUersId方法,所以在正式环境中直接使用 用户的ID或是能代表接收人身份的唯一值 的话,每创建一个连接GetUserId时就 没问题了,发消息时,使用这个唯一值 去拿到 Clients.User(reUserId) 就可以对这个用户发消息了
原文:https://www.cnblogs.com/JalanWang/p/11152584.html