You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET Core Web API的SignalR中获取用户2的Connection Id

解决SignalR中获取目标用户ConnectionId并发送消息的问题

核心问题分析

你当前代码里的Clients.User(user)如果没传入正确的目标用户标识,只会拿到当前发起请求的用户(用户1)的连接信息。要实现用户1向用户2发消息,关键是正确关联用户与ConnectionId,并能精准查询到目标用户的ConnectionId。


方案1:手动维护用户-ConnectionId映射表

通过SignalR的连接生命周期事件,记录和更新用户与ConnectionId的对应关系:

  1. 连接建立时记录映射
// 定义全局存储,分布式场景请替换为Redis等分布式存储
private static readonly Dictionary<string, HashSet<string>> _userConnections = new Dictionary<string, HashSet<string>>();

public override async Task OnConnectedAsync()
{
    // 获取当前用户的唯一标识(比如用户名、用户ID,根据你的认证逻辑调整)
    var targetUserId = Context.User.Identity.Name;
    
    lock (_userConnections)
    {
        if (!_userConnections.ContainsKey(targetUserId))
        {
            _userConnections.Add(targetUserId, new HashSet<string>());
        }
        _userConnections[targetUserId].Add(Context.ConnectionId);
    }
    
    await base.OnConnectedAsync();
}
  1. 连接断开时移除映射
public override async Task OnDisconnectedAsync(Exception exception)
{
    var targetUserId = Context.User.Identity.Name;
    
    lock (_userConnections)
    {
        if (_userConnections.TryGetValue(targetUserId, out var connectionIds))
        {
            connectionIds.Remove(Context.ConnectionId);
            if (connectionIds.Count == 0)
            {
                _userConnections.Remove(targetUserId);
            }
        }
    }
    
    await base.OnDisconnectedAsync(exception);
}
  1. 发送消息时查询目标用户的ConnectionId并发送
public async Task SendMessage(string targetUserId, string message)
{
    if (_userConnections.TryGetValue(targetUserId, out var connectionIds))
    {
        foreach (var connectionId in connectionIds)
        {
            await Clients.Client(connectionId).SendAsync("ReceiveMessage", message);
        }
    }
}

方案2:直接使用SignalR内置的User方法(无需手动维护ConnectionId)

如果你的系统已经正确完成用户认证,SignalR会自动关联用户标识与ConnectionId,此时直接通过目标用户标识发送即可:

public async Task SendMessage(string targetUserId, string message)
{
    // 这里的targetUserId必须是用户2的唯一标识(和认证时的用户标识一致)
    await Clients.User(targetUserId).SendAsync("ReceiveMessage", message);
}

你之前代码里的user变量错误使用了当前用户的标识,这才导致每次拿到的都是用户1的ConnectionId,替换为用户2的标识即可解决问题。


关键注意事项

  • 若用户存在多端登录情况,一个用户会对应多个ConnectionId,因此映射表需存储集合而非单个值。
  • 分布式部署场景下,禁止使用内存字典存储映射关系,必须改用Redis等分布式存储保证数据一致性。

内容的提问来源于stack exchange,提问作者Abdalhmeed Shishani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:32:14