SignalR 提供了强大的消息发送机制,支持向特定用户、组或所有客户端广播消息。
///
/// 向特定用户发送消息
///
/// 接收者
/// 发送的消息
///
public async Task SendPrivateMsgAsync(string toUserName, string content)
{
try
{
var senderUserID = Context.UserIdentifier;
var senderUser= await userManager.FindByIdAsync(senderUserID);
var toUser = await userManager.FindByNameAsync(toUserName);
await Clients.User(toUser.Id.ToString()).SendAsync("ReceivePrivateMsg", senderUser.UserName, content);
}
catch (Exception ex)
{
throw;
}
}
代码如下(示例):
// 在内存中缓存组信息以提高性能
private static readonly ConcurrentDictionary<string, GroupInfo> _groups = new ConcurrentDictionary<string, GroupInfo>();
///
/// 创建自定义组
///
///
///
public async Task CreateGroup(string groupName)
{
long userId = Convert.ToInt64(Context.UserIdentifier);
if (_groups.ContainsKey(groupName))
{
await Clients.Caller.SendAsync("GroupCreationFailed", "组已存在");
return;
}
// 创建新组并保存到数据库
var group = new Group
{
GroupName = groupName,
CreatedAt = DateTime.UtcNow,
CreatorId = userId
};
myDbContext.Groups.Add(group);
await myDbContext.SaveChangesAsync();
// 添加到内存缓存
var groupInfo = new GroupInfo
{
GroupId = group.GroupId,
GroupName = groupName,
MemberIds = new HashSet<long> { userId }
};
_groups.TryAdd(groupName, groupInfo);
// 创建者自动加入组
await AddUserToGroup(groupName, userId);
await Clients.All.SendAsync("GroupCreated", groupName);
}
private async Task AddUserToGroup(string groupName, long userId)
{
try
{
var groupInfo = _groups[groupName];
// 添加到数据库
var groupMember = new GroupMember
{
GroupId = groupInfo.GroupId,
UserId = userId,
JoinedAt = DateTime.UtcNow
};
myDbContext.GroupMembers.Add(groupMember);
await myDbContext.SaveChangesAsync();
}
catch (Exception)
{
throw;
}
}
///
/// 加入自定义组
///
///
///
public async Task JoinGroup(string groupName)
{
var userId = Convert.ToInt64(Context.UserIdentifier);
if (!_groups.TryGetValue(groupName, out var groupInfo))
{
await Clients.Caller.SendAsync("JoinGroupFailed", "组不存在");
return;
}
if (groupInfo.MemberIds.Contains(userId))
{
await Clients.Caller.SendAsync("JoinGroupFailed", "您已在该组中");
return;
}
// 添加用户到组
await AddUserToGroup(groupName, userId);
// 更新内存缓存
groupInfo.MemberIds.Add(userId);
// 将用户加入 SignalR 组
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
await Clients.Group(groupName).SendAsync("UserJoinedGroup", Context.User.Identity.Name, groupName);
//try
//{
// if (_groups.ContainsKey(groupName))
// {
// await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
// _groups[groupName].Add(Context.ConnectionId);
// await Clients.Group(groupName).SendAsync("UserJoinGroup", Context.UserIdentifier, groupName); ;
// }
//}
//catch (Exception ex)
//{
// throw;
//}
}
///
/// 用户离开自定义组
///
///
///
public async Task LeaveGroup(string groupName)
{
var userId = Convert.ToInt64(Context.UserIdentifier);
if (!_groups.TryGetValue(groupName, out var groupInfo) ||
!groupInfo.MemberIds.Contains(userId))
{
await Clients.Caller.SendAsync("LeaveGroupFailed", "您不在该组中");
return;
}
// 从组中移除用户
await RemoveUserFromGroup(groupName, userId);
// 更新内存缓存
groupInfo.MemberIds.Remove(userId);
// 如果组为空,删除组
if (groupInfo.MemberIds.Count == 0)
{
await DeleteGroup(groupName);
}
else
{
// 将用户移出 SignalR 组
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
await Clients.Group(groupName).SendAsync("UserLeftGroup", Context.User.Identity.Name, groupName);
}
//if (_groups.ContainsKey(groupName) && _groups[groupName].Contains(Context.ConnectionId))
//{
// await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
// _groups[groupName].Remove(Context.ConnectionId);
// await Clients.Group(groupName).SendAsync("UserLeaveGroup",Context.UserIdentifier, groupName);
//}
}
private async Task RemoveUserFromGroup(string groupName, long userId)
{
var groupInfo = _groups[groupName];
// 从数据库移除
var groupMember = await myDbContext.GroupMembers
.FirstOrDefaultAsync(gm => gm.GroupId == groupInfo.GroupId && gm.UserId == userId);
if (groupMember != null)
{
myDbContext.GroupMembers.Remove(groupMember);
await myDbContext.SaveChangesAsync();
}
}
private async Task DeleteGroup(string groupName)
{
if (_groups.TryRemove(groupName, out var groupInfo))
{
// 从数据库删除组
var group = await myDbContext.Groups.FindAsync(groupInfo.GroupId);
if (group != null)
{
myDbContext.Groups.Remove(group);
await myDbContext.SaveChangesAsync();
}
await Clients.All.SendAsync("GroupDeleted", groupName);
}
}
关键点
///
/// 向所有用户发送消息
///
///
///
///
[Authorize(Roles = "admin")]
public async Task SendMessageAsync(string user, string content)
{
//var connectionId = this.Context.ConnectionId;
//string msg = $"{connectionId},{DateTime.Now.ToString()}:{user}";
await Clients.All.SendAsync("ReceiveMsg", user, content);
}
///
/// 向除发送者外的所有客户端发送消息
///
///
///
///
public async Task SendOthersMsg(string sender, string content)
{
await Clients.Others.SendAsync("ReceiveMsg",sender, content);
}
///
/// 向管理员组AdminUsers发送消息
///
///
///
///
public async Task SendAdminMsgAsync(string sender, string content)
{
await Clients.Group("AdminUsers").SendAsync("ReceiveAdminMsg", sender, content);
}
代码示例:
// 创建新连接
state.connection = new signalR.HubConnectionBuilder()
.withUrl(state.serverUrl, {
accessTokenFactory: () => token,
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
})
.withAutomaticReconnect()
.configureLogging(signalR.LogLevel.Information)
.build();
// 注册消息处理程序
state.connection.on("ReceiveMsg", (user, message) => {
state.messages.push({
type: 'broadcast',
sender: `${user}(广播消息)`,
content: message,
timestamp: new Date()
});
});
state.connection.on("ReceivePrivateMsg", (sender, message) => {
if (!sender || !message) return;
state.messages.push({
type: 'private',
sender: `${sender} (私信)`,
content: message,
timestamp: new Date()
});
});
state.connection.on("ReceiveGroupMsg", (sender, group, message) => {
state.messages.push({
type: 'group',
sender: `${sender} (${group})`,
content: message,
group: group,
timestamp: new Date()
});
});
......
// 启动连接
await state.connection.start();
通过以上方法,你可以灵活实现 SignalR 的部分消息发送功能,满足不同场景下的实时通信需求。