SignalR 是一个开源的服务端与客户端实现实时通讯的插件,更据微软asp.net core 文档解释如下:
服务端:
使用的是 asp.net core3.1,在Startup.cs 的配置服务的方法里添加services.AddSignalR();
然后在Configure 方法里配置路由
图片箭头指向的字符串是到时候客户端请求使用的的路径
创建一个类 HubUtil.cs此类用来实现接收来在客户端消息和发送消息给客户端功能
该类继承Hub。
public class ChatHub : Hub
{
public Task SendMessage(string user, string message)
{
return Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
一个简单的服务端就完成了
附上微软文档的详细属性和方法说明:
强类型:
使用的缺点 SendAsync
是它依赖于幻字符串来指定要调用的客户端方法。 如果客户端中的方法名称拼写错误或缺失,则这会使代码对运行时错误开放。
使用的替代方法 SendAsync
是使用强类型 Hub
HubChatHub
客户端方法已提取到名为的接口 IchatClien
t
(官方文档解释)
public interface ICommonClient
{
///
/// 测试用
///
///
///
///
Task ReceiveMessage(string user, string message);
///
/// 添加连接客户端
///
///
///
Task AddClient(MoHubUser user);
///
/// 获取连接客户端人数
///
///
///
Task GetClientCount(int count);}
public class StronglyTypedChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
}
public Task SendMessageToCaller(string message)
{
return Clients.Caller.ReceiveMessage(message);
}
}
处理连接事件
#region SignalR中心 API 提供 OnConnectedAsync 和 OnDisconnectedAsync 虚拟方法来管理和跟踪连接。
///
/// 处理连接事件
/// 重写 OnConnectedAsync 虚拟方法,以便在客户端连接到集线器时执行操作,如将其添加到组。
///
///
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
///
/// 客户端断开连接时执行此重写方法
/// 重写 OnDisconnectedAsync 虚拟方法,以便在客户端断开连接时执行操作。
/// 如果客户端故意断开连接( connection.stop() 例如,通过调用),则 exception 参数将为 null 。
/// 但是,如果客户端由于错误(例如网络故障)而断开连接,则 exception 参数将包含描述失败的异常。
///
///
///
public override async Task OnDisconnectedAsync(Exception exception)
{
var user = lstClient.SingleOrDefault(x => x.Id == Context.ConnectionId);
if (user != null)
{
lstClient.Remove(user);
await Clients.All.GetClientCount(lstClient.Count);
}
await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnDisconnectedAsync(exception);
}
#endregion
我自己的完整的HubUtil.cs:
public class HubUtil : Hub
{
public static List lstClient = new List();
///
/// 测试用
///
///
///
///
public async void SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
return ;
}
///
/// 添加连接客户端
///
///
///
public async void AddClient(MoHubUser user)
{
user.Id = Context.ConnectionId;
user.date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
user.Type = BEAN.ENUM.EnumSYSClass.EnumClientType.Users;
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
if (!lstClient.Any(b => b.Id == user.Id || b.NickName == user.NickName) )
{
//user.NickName = auser.Name;
lstClient.Add(user);
}
await Clients.All.GetClientCount(lstClient.Count);
await Clients.Users(Context.UserIdentifier).ReceiveMessage("UserConnectionID", Context.ConnectionId);
return;
}
///
/// 获取连接人数
///
///
public Task GetClientsCount()
{
return Clients.Users(Context.UserIdentifier).GetClientCount(lstClient.Count);
}
#region SignalR中心 API 提供 OnConnectedAsync 和 OnDisconnectedAsync 虚拟方法来管理和跟踪连接。
///
/// 处理连接事件
/// 重写 OnConnectedAsync 虚拟方法,以便在客户端连接到集线器时执行操作,如将其添加到组。
///
///
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
///
/// 客户端断开连接时执行此重写方法
/// 重写 OnDisconnectedAsync 虚拟方法,以便在客户端断开连接时执行操作。
/// 如果客户端故意断开连接( connection.stop() 例如,通过调用),则 exception 参数将为 null 。
/// 但是,如果客户端由于错误(例如网络故障)而断开连接,则 exception 参数将包含描述失败的异常。
///
///
///
public override async Task OnDisconnectedAsync(Exception exception)
{
var user = lstClient.SingleOrDefault(x => x.Id == Context.ConnectionId);
if (user != null)
{
lstClient.Remove(user);
await Clients.All.GetClientCount(lstClient.Count);
}
await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnDisconnectedAsync(exception);
}
#endregion
}
为了更直观一些我写了一个web用来显示客户端连接人数和一些详细的发送消息内容:
在wwwroot文件夹里引用添加signalr.js
然后引用
Js连接SignalR服务端
const connection = new signalR.HubConnectionBuilder()
.withUrl("@Url.Content("~")/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
withUrl 里的就是在Startup.cs 配置路由那里写的一样
再写一个连接方法
async function start() {
try {
await connection.start();
console.log("connected");
const encodedMsg = `系统 : 连接成功!`;
const li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("content").appendChild(li);
connection.invoke("GetClientsCount");
} catch (err) {
console.log(err);
setTimeout(() => start(), 5000);
}
};
//此方法是连接意外关闭时执行的
connection.onclose(async () => {
await start();
});
//接收来自服务端的消息
connection.on("ReceiveMessage", (user, message) => {
const encodedMsg = `${user} : ${message}`;
const li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("content").appendChild(li);
});
//接收来自服务端的消息
connection.on("GetClientCount", function (count) {
document.getElementById('clientCountBox').textContent = '连接人数:' + count;
})
}
红字部分对应写的接口名称和参数
//发送消息给服务端
function send() {
connection.invoke("SendMessage", "服务器", document.getElementById("inputContent").value).catch(err => console.error(err));
红字部分对应HubUitl.cs 类里的方法
完整html+js:
@*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
}
头条新闻控制台输出
连接人数:
@**@
运行:
成功!