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

SignalR如何向除请求发起者外的所有用户发送消息

问题分析与解决方案

错误原因

你当前的代码存在两个核心问题:

  1. AllExcept参数用错:AllExcept方法需要传入要排除的SignalR连接ID数组,而不是用户名/组名,你传入用户名自然不会生效。
  2. GroupExcept参数用错:GroupExcept的第一个参数是目标组名,第二个参数是要排除的连接ID列表,你两次传入组名等于没有排除任何连接,所以所有组内用户都能收到消息。

解决方案

结合你已经将每个用户的所有连接加入对应用户名组的设计,提供两种适配你需求的实现方式:

方法1:给所有用户发消息,排除当前请求用户(推荐)

因为你已经把用户的所有连接都归类到以用户名命名的组中,直接用AllGroupsExcept方法排除当前用户的组即可,无需维护额外的连接映射:

string currentUserName = this.User.Identity.Name ?? "Service";
// 向所有组发送消息,排除当前用户的组(即当前用户的所有连接都收不到)
await _hubContext.Clients.AllGroupsExcept(currentUserName).SendAsync("AtualizaPosicaoCardOP", "Mensagem aqui");

方法2:精确排除当前用户的单个/多个连接

如果需要针对当前用户的特定连接进行排除,需要先在Hub中维护用户名与连接ID的映射关系:

// 在MesHub类中添加并发安全的连接映射
private static readonly ConcurrentDictionary<string, List<string>> UserConnections = new ConcurrentDictionary<string, List<string>>();

public override Task OnConnectedAsync()
{
    string name = Context.User.Identity.Name ?? "Service";
    // 将当前连接ID添加到对应用户的连接列表
    UserConnections.AddOrUpdate(
        name,
        new List<string> { Context.ConnectionId },
        (key, existingList) => {
            existingList.Add(Context.ConnectionId);
            return existingList;
        });

    await Groups.AddToGroupAsync(Context.ConnectionId, name);
    return base.OnConnectedAsync();
}

public override Task OnDisconnectedAsync(Exception exception)
{
    string name = Context.User.Identity.Name ?? "Service";
    // 断开连接时移除对应映射
    if (UserConnections.TryGetValue(name, out var connections))
    {
        connections.Remove(Context.ConnectionId);
        if (connections.Count == 0)
        {
            UserConnections.TryRemove(name, out _);
        }
    }
    return base.OnDisconnectedAsync(exception);
}

然后在控制器中通过用户名获取连接ID列表,再用AllExcept排除:

string currentUserName = this.User.Identity.Name ?? "Service";
if (MesHub.UserConnections.TryGetValue(currentUserName, out var connectionIds))
{
    // 排除当前用户的所有连接,给其他用户发消息
    await _hubContext.Clients.AllExcept(connectionIds.ToArray()).SendAsync("AtualizaPosicaoCardOP", "Mensagem aqui");
}
else
{
    // 当前用户无在线连接,直接发送给所有用户
    await _hubContext.Clients.All.SendAsync("AtualizaPosicaoCardOP", "Mensagem aqui");
}

GroupExcept的正确用法

如果你的需求是给某个特定组发消息,同时排除组内的部分连接,正确写法如下:

// 示例:给名为"TargetGroupName"的组发消息,排除连接ID为"connId1"、"connId2"的客户端
await _hubContext.Clients.GroupExcept("TargetGroupName", new[] { "connId1", "connId2" }).SendAsync("AtualizaPosicaoCardOP", "Mensagem aqui");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 11:57:46