我一直觉得学习的最好方法就是先让程序能够正常运行,才去学习他的原理,剖析他的细节.
就好像这个图:
所以,我们先跟着官方文档,创建一个 SignalR 应用: https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio
这个例子一共涉及到下面几个步骤:
- 自定义中心 ChatHub ;
- 在启动类 Startup 中启用 SignalR 服务,并添加路由;
- 编写客户端JS
- 下载 SignalR 官方JS.
自定义中心 : ChatHub
???public class ChatHub : Hub ???{ ???????????public async Task SendMessage(string user, string message) ???????{ ???????????await Clients.All.SendAsync("ReceiveMessage", user, message); ???????} ???}
"Hub" 一词,有的地方翻译成"集线器",有的地方翻译成"中心",对于我这种非科班出身的人来说,还是"中心"听起简单点.
对于基类 Hub ,xml 是这样说的 : A base class for a SignalR hub. SignalR 中心的基类.
这个很简单,看这些名字就知道他们是干嘛用的,具体的描述可以看官方文档.
中心的作用可以这样简单的描述:
通过中心,我们能在服务器的代码中定义客户端可以调用的方法(必须是 public);
通过中心,我们能在客户端的代码中定义服务器可以调用的方法.
上述代码,我们通过继承 Hub ,定义了一个自己的中心 : ChatHub (聊天中心) ,在这个类里面,我们做了下面两件事:
- 定义了客户端可以调用的方法 : SendMessage(string user, string message)
- 调用了所有连接上 Hub 的客户端的 ReceiveMessage 方法,并将 user,message 两个字符串作为入参传入该方法.
中心定义好了,肯定需要启用
在启动类 Startup 中启用 SignalR 服务,并添加路由
???????public void ConfigureServices(IServiceCollection services) ???????{ ???????????...... ???????????????//注册 SignalR 服务 ???????????services.AddSignalR(); ???????}
???????public void Configure(IApplicationBuilder app, IHostingEnvironment env) ???????{ ???????????...... ???????????//设置 SignalR 中心路由 ???????????app.UseSignalR(routes => { routes.MapHub<ChatHub>("/chatHub"); }); ???????????app.UseMvc(); ???????}
编写客户端JS
"use strict";//不太明白这句话是什么意思...//创建一个连接到我们创建的 ChatHub 的 connection.var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();//定义客户端的方法,方法名: ReceiveMessage ,两个入参.//注意,这个方法就是服务器要调用的方法,服务器和客户端的名字一定要一样.connection.on("ReceiveMessage", function (user, message) { ???var msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); ???var encodedMsg = user + " says " + msg; ???var li = document.createElement("li"); ???li.textContent = encodedMsg; ???document.getElementById("messagesList").appendChild(li);});//开启连接.connection.start().catch(function (err) { ???return console.error(err.toString());});document.getElementById("sendButton").addEventListener("click", function (event) { ???var user = document.getElementById("userInput").value; ???var message = document.getElementById("messageInput").value; ???//调用服务器的 SendMessage 方法,并传入两个入参.这和委托的调用太像了. ???connection.invoke("SendMessage", user, message).catch(function (err) { ???????return console.error(err.toString()); ???}); ???event.preventDefault();});
上面的 ChatHub 类的 SendAsync 方法在调用客户端的方法时,方法名是直接写的 字符串 : "ReceiveMessage"
官方不推荐这样写,因为不是强类型,可能出现运行时错误,因此建议使用强类型的中心
(顺带附上了一些额外的功能):
???//建议使用下面的强类型方式 ???//方法二 ???public interface IChatClient ???{ ???????//就算是这种强类型方式,客户端定义的方法名也必须和这个方法名一样,包括签名. ???????Task ReceiveMessage(string user, string message); ???} ???public class StronglyTypedChatHub : Hub<IChatClient> ???{ ???????//[HubMethodName("hello")] 可以改名,如果改了名,前端也要跟着改,别忘了. ???????public async Task SendMessage(string user, string message) ???????{ ???????????//调用客户端定义的 ReceiveMessage 方法. ???????????//throw new HubException("哈哈,出错了!");//可以向客户端发送异常.只会向当前调用的客户端发送,并且只发送 message ,不会发送堆栈信息. ???????????await Clients.All.ReceiveMessage($"{GetHashCode()}" + user, message);//传递 hashCode 是为了证明,每次调用都是不同的实例.所以官方说不要在"中心"里面存状态. ???????} ???????//该方法可以在客户端连接上后,执行操作 ???????public override async Task OnConnectedAsync() ???????{ ???????????await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users"); ???????????await base.OnConnectedAsync(); ???????} ???????//同理,当客户端断开连接时执行的操作 ???????public override async Task OnDisconnectedAsync(Exception exception) ???????{ ???????????await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users"); ???????????await base.OnDisconnectedAsync(exception); ???????} ???}
当然,注册路由的代码也得换了 : app.UseSignalR(routes => { routes.MapHub<StronglyTypedChatHub>("/chatHub"); });
好困,明天继续
ASP.NET Core 2.2 基础知识(十六) SignalR (未完待续)
原文地址:https://www.cnblogs.com/refuge/p/10237131.html