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) 就可以对这个用户发消息了
来源: http://www.bubuko.com/infodetail-3117568.html