SignalR 服务端/SignalR C#客户端/SignalR js客户端
SignalR 服务端/SignalR C#客户端/SignalR js客户端
服务端
Program.cs
SignalRHub
是自定义的操作类,/chathub
是客户端访问的路由
builder.Services.AddSignalR();
builder.Services.AddSingleton<SignalRUsers>();
app.MapHub<SignalRHub>("/chathub");
SignalRUsers 客户端列表
public class SignalRUsers
{
// 保存客户端的列表
public ConcurrentDictionary<string, string> list { get; set; }
public SignalRUsers()
{
list = new System.Collections.Concurrent.ConcurrentDictionary<string, string>();
}
}
SignalRHub
public class SignalRHub : Hub
{
readonly SignalRUsers users;
public SignalRHub(SignalRUsers _users) {
users = _users;
}
/// <summary>
/// 连接事件
/// </summary>
/// <returns></returns>
public override Task OnConnectedAsync()
{
// 获取客户端自定义id
var userid = Context.GetHttpContext().Request.QueryString.Get("userid");
//客户端连接id
var id = Context.ConnectionId;
//将客户端添加到列表
if(!users.list.ContainsKey(userid))
{
users.list.TryAdd(userid, id);
}
else
{
//每次重新连接,客户端连接的id都不一样,这里更新客户端连接id
users.list[userid] = id;
}
return base.OnConnectedAsync();
}
/// <summary>
/// 客户端断连事件
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
public override Task OnDisconnectedAsync(Exception? exception)
{
return base.OnDisconnectedAsync(exception);
}
/// <summary>
/// 发送消息
/// 也可以由客户端调用
/// 可以创建多个类似方法实现复杂功能
/// </summary>
/// <param name="user"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task SendMessage(string user, string message)
{
//取得客户端连接id
var id = users.list[user];
//触发所有客户端定义的"ReceiveMessage"方法
await Clients.All.SendAsync("ReceiveMessage", user, message);
//触发指定客户端定义的"ReceiveMessage"方法
await Clients.Clients(id).SendAsync("ReceiveMessage", user, message);
}
}
从QueryString
取值的方法
public static string Get(this QueryString query, string name)
{
var str = query.ToString().Trim('?');
if (string.IsNullOrEmpty(str)) return null;
var arr = str.Split('&');
var dic = new Dictionary<string, string?>();
foreach (var i in arr)
{
var item = i.Split('=');
dic.Add(item[0], item.Length > 1 ? item[1] : null);
}
var q = dic.Any(x => x.Key == name);//[name];//.FirstOrDefault(x => x.Key == name);
if (!q) return null;
return System.Web.HttpUtility.UrlDecode(dic[name]);
return "";
}
服务端在其它业务类中调用SignalRHub
中的方法,实现操控客户端
//注入 Hub类
private readonly IHubContext<SignalRHub> _hubContext;
public NotificationService(IHubContext<SignalRHub> hubContext)
{
_hubContext = hubContext;
//向所有客户端发送消息
_hubContext.Clients.All.SendAsync("ReceiveMessage", "123456", "66666");
}
C#客户端
NuGet 添加包
Microsoft.AspNetCore.SignalR.Client
Program.cs
//注册客户端
builder.Services.AddSingleton<Client>();
//注册一个后台任务,定时检查连接状态,重连
builder.Services.AddHostedService<SClient>();
Client
using Microsoft.AspNetCore.SignalR.Client;
public class Client
{
HubConnection _connection;
public Client() {
_connection = new HubConnectionBuilder()
.WithUrl("http://localhost:5047/chatHub?userid=654321") // 替换为你的 SignalR Hub 的 URL
.Build();
// 订阅 Hub 发送的消息
_connection.On<string, string>("ReceiveMessage", (user, message) =>
{
Console.WriteLine($"Received: {message}");
});
}
public void Send()
{
// 调用服务端指定方法
_connection.SendAsync("SendMessage", "654321","123456789");
}
/// <summary>
/// 连接或者重连服务器
/// </summary>
public void ReConnected()
{
//判断连接状态
if (_connection != null && _connection.State == HubConnectionState.Disconnected)
{
Console.WriteLine("连接服务器");
// 开始连接
_connection.StartAsync();
//是否连接成功
if(_connection.State == HubConnectionState.Connecting)
{
Console.WriteLine("连接成功");
}
else
{
Console.WriteLine("连接失败");
}
}
}
}
SClient
public class SClient : BackgroundService
{
//引入客户端类
Client _sc;
public SClient(Client sc) {
_sc = sc;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
Task.Run(() =>
{
while (true)
{
_sc.Send();//发送消息到服务端
_sc.ReConnected();//重连
Task.Delay(5000).Wait();//每5秒检查一次状态
}
});
return Task.CompletedTask;
}
}
js客户端
右键
项目
-添加
-客户端库
提供程序选择unpkg
,搜索signalr
,选择microsoft/signalr
选择特定文件
dist
-browser
-signalr.js
和signalr.min.js
引入signalr.js
或signalr.min.js
//创建连接对象 userid 是自定义的客户端id
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub?userid=123456").build();
//客户端方法,由服务端触发
connection.on("ReceiveMessage", function (user, message) {
console.log(`${user} says ${message}`);
});
//是否连接成功
var _isConn = false;
connection.start().then(function () {
//连接成功
_isConn = true;
var user = "123456";//客户端id,经过服务端可以将消息发送到指定的客户端
var message = "666";//消息内容
//调用服务端方法
connection.invoke("SendMessage", user, message).catch(function (err) {
return console.error(err.toString());
});
}).catch(function (err) {
//连接失败
return console.error(err.toString(),666);
});