在C#的实时通信开发中,SignalR提供了便捷的组播能力,允许开发者将连接划分到不同的组,再向指定组内的所有连接批量发送消息,避免向所有客户端广播造成的资源浪费。这种机制非常适合聊天室、协同编辑、实时通知等场景,只需要将相关用户加入同一个组,就能精准推送消息。

SignalR组的基础操作
实现组播的第一步是管理组的成员,SignalR的Hub类提供了内置的组操作方法,开发者可以直接调用这些方法完成组的加入、移除操作。
客户端加入组
客户端可以通过调用服务端的Hub方法主动加入指定组,服务端方法需要使用Groups.AddToGroupAsync方法将当前连接ID添加到目标组。
// 服务端Hub代码
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
public class ChatHub : Hub
{
// 客户端调用此方法加入指定组
public async Task JoinGroup(string groupName)
{
// 将当前连接加入目标组
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
// 向组内其他成员发送通知
await Clients.OthersInGroup(groupName).SendAsync("ReceiveMessage", $"{Context.ConnectionId} 加入了组 {groupName}");
}
}
客户端离开组
当客户端不再需要接收组消息时,可以主动离开组,或者服务端在连接断开时自动清理组关系,服务端使用Groups.RemoveFromGroupAsync方法移除组成员。
// 服务端Hub代码,客户端主动离开组
public async Task LeaveGroup(string groupName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
await Clients.OthersInGroup(groupName).SendAsync("ReceiveMessage", $"{Context.ConnectionId} 离开了组 {groupName}");
}
向特定组发送消息的实现
完成组的成员管理后,就可以调用对应的组播方法向特定组发送消息,SignalR提供了多种组播的客户端选择方式。
向指定组所有成员发消息
使用Clients.Group方法可以选中目标组的所有连接,然后调用SendAsync发送消息,组内所有在线成员都会收到该消息。
// 服务端向指定组发送消息的方法
public async Task SendToGroup(string groupName, string message)
{
// 向组groupName的所有成员发送消息
await Clients.Group(groupName).SendAsync("ReceiveGroupMessage", message);
}
排除特定连接发消息
如果需要向组发送消息但排除当前发送者,可以使用Clients.OthersInGroup方法,该方法会选中组内除了当前连接之外的所有成员。
// 向组内其他成员发送消息,排除当前发送者
public async Task SendToOthersInGroup(string groupName, string message)
{
await Clients.OthersInGroup(groupName).SendAsync("ReceiveGroupMessage", $"来自其他成员的消息:{message}");
}
客户端接收组消息的实现
客户端需要注册对应的消息接收方法,才能收到服务端发送的组消息,以下是JavaScript客户端的示例代码。
// 创建SignalR连接
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.build();
// 注册接收组消息的方法
connection.on("ReceiveGroupMessage", (message) => {
console.log("收到组消息:", message);
// 将消息展示到页面
const messageDiv = document.createElement("div");
messageDiv.textContent = message;
document.getElementById("messageList").appendChild(messageDiv);
});
// 启动连接
async function startConnection() {
try {
await connection.start();
console.log("SignalR连接已建立");
} catch (err) {
console.error("连接失败:", err);
setTimeout(startConnection, 5000);
}
}
startConnection();
// 加入组的操作
function joinGroup() {
const groupName = document.getElementById("groupNameInput").value;
connection.invoke("JoinGroup", groupName);
}
// 发送组消息的操作
function sendGroupMessage() {
const groupName = document.getElementById("groupNameInput").value;
const message = document.getElementById("messageInput").value;
connection.invoke("SendToGroup", groupName, message);
}
组播的注意事项
- 组是临时存在的,当组内没有连接时,组会被自动清理,不需要手动删除空组。
- 连接断开时,SignalR会自动将该连接从所有加入的组中移除,不需要手动调用离开组方法。
- 组名区分大小写,发送消息和加入组时使用的组名必须完全一致,否则无法匹配到目标组。
- 如果需要在应用重启后保留组关系,需要自定义组存储,默认组信息是存储在内存中的,重启后会丢失。
常见问题解答
如何向多个组同时发送消息?
可以多次调用Clients.Group方法,或者使用Clients.Groups方法传入多个组名,示例代码如下:
// 向多个组发送消息
public async Task SendToMultipleGroups(string[] groupNames, string message)
{
await Clients.Groups(groupNames).SendAsync("ReceiveGroupMessage", message);
}
组播消息是否保证送达?
SignalR的组播消息基于实时连接,如果客户端在消息发送时处于离线状态,不会收到该消息,需要结合持久化存储实现离线消息功能。
C#_SignalR组播Hub组消息发送实时通信修改时间:2026-07-07 09:18:32