ASP.NET Core 2.2 基础知识(十六) SignalR 概述
我一直觉得学习的最好方法就是先让程序能够正常运行,才去学习他的原理,剖析他的细节.
就好像这个图:
所以,我们先跟着官方文档,创建一个 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 ,不会发送堆栈信息. //Clients.Caller 当前客户端
//Clients.Others 当前客户端的其他客户端
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"); });
好困,明天继续
2019.1.9
复制一段官方的文档.
SignalR 是什么?
ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程。 实时 Web 功能使服务器端代码能够即时将内容推送到客户端。
SignalR 的适用对象:
- 需要来自服务器的高频率更新的应用。 例如:游戏、社交网络、投票、拍卖、地图和 GPS 应用。
- 仪表板和监视应用。 示例包括公司仪表板、销售状态即时更新或行程警示。
- 协作应用。 协作应用的示例包括白板应用和团队会议软件。
- 需要通知的应用。 社交网络、电子邮件、聊天、游戏、行程警示以及许多其他应用都使用通知。
SignalR 提供了一个用于创建服务器到客户端远程过程调用(RPC)的 API。 RPC 通过服务器端 .NET Core 代码调用客户端上的 JavaScript 函数。
以下是 ASP.NET Core SignalR 的一些功能:
- 自动管理连接。
- 同时向所有连接的客户端发送消息。 例如,聊天室。
- 将消息发送到特定的客户端或客户端组。
- 扩展以处理增加的流量。
传输
SignalR 支持几种方法用于处理实时通信:
- WebSockets
- 服务器发送事件
- 长轮询
SignalR 会从服务器和客户端支持的功能中自动选择最佳传输方法
中心
SignalR 使用中心在客户端和服务器之间进行通信。
“中心”是一种高级管道,允许客户端和服务器相互调用方法。 SignalR 自动处理跨计算机边界的调度,允许客户端和服务器相互调用方法。 可以将强类型参数传递给方法,从而启用模型绑定。 SignalR 提供两个内置中心协议:基于 JSON 的文本协议和基于 MessagePack 的二进制协议。 与 JSON 相比,MessagePack 创建的消息通常比较小。 旧版浏览器必须支持 XHR 2 才能提供 MessagePack 协议支持。
中心通过发送包含客户端方法的名称和参数的消息来调用客户端代码。 使用配置的协议对作为方法参数发送的对象进行反序列化。 客户端会尝试将方法名称与客户端代码中的方法匹配。 当客户端找到匹配项时,它会调用该方法并将反序列化的参数数据传递给它。
发送中心外的信息
上面讲的例子,客户端和服务器的消息都是在"中心"里面流动.实际上,中心还可以把中心之外的信息发送给客户端.(这句话可能有点绕),看示例就明白了.
新建一个测试控制器, 依然通过依赖注入得到 IHubContext 类的实例, StronglyTypedChatHub 类就是上面例子中的那个自定义的强类型中心.
[Route("api/[controller]")]
[ApiController]
public class TestController
{
private IHubContext<StronglyTypedChatHub, IChatClient> _context; public TestController(IHubContext<StronglyTypedChatHub, IChatClient> context)
{
_context = context;
} public void Get()
{
_context.Clients.All.ReceiveMessage("admin", "在座的各位都是垃圾!");
}
}
测试效果:
这个是强类型中心的例子,下面是普通中心的例子:
[Route("api/[controller]")]
[ApiController]
public class TestController
{ //强类型中心
//private IHubContext<StronglyTypedChatHub, IChatClient> _context; //public TestController(IHubContext<StronglyTypedChatHub, IChatClient> context)
//{
// _context = context;
//} //普通中心
private IHubContext<ChatHub> _context; public TestController(IHubContext<ChatHub> context)
{
_context = context;
} public void Get()
{
//这种调用客户端方法的方式,好别扭
_context.Clients.All.SendAsync("ReceiveMessage", "admin", "在座的各位都是垃圾!!!");
}
}
ASP.NET Core 2.2 基础知识(十六) SignalR 概述的更多相关文章
- ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述
为了方便演示,以 .NET Core 控制台应用程序讲解. 我们新建一个控制台应用程序,安装 "Newtonsoft.Json" Nuget 包,然后右键点击该项目,选择" ...
- ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 请求
可以注册 IHttpClientFactory 并将其用于配置和创建应用中的 HttpClient 实例. 这能带来以下好处: 提供一个中心位置,用于命名和配置逻辑 HttpClient 实例. 例如 ...
- ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)
要啥自行车,直接看手表 //返回基元类型 public string Get() { return "hello world"; } //返回复杂类型 public Person ...
- ASP.NET Core 2.2 基础知识(十) Web服务器 - Kestrel
ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...
- ASP.NET Core 2.2 基础知识(十五) Swagger
安装 Nuget 包 注册 Swagger public void ConfigureServices(IServiceCollection services) { services.AddMvc() ...
- ASP.NET Core 2.2 基础知识(十三) WebAPI 概述
我们先创建一个 WebAPI 项目,看看官方给的模板到底有哪些东西 官方给出的模板: [Route("api/[controller]")] [ApiController] pub ...
- ASP.NET Core 2.2 基础知识(十一) ASP.NET Core 模块
ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...
- ASP.NET Core 2.2 基础知识(九) 使用托管服务实现后台任务
在 ASP.NET Core 中,后台任务作为托管服务实现.托管服务是一个类,而且必须实现 IHostedService 接口,该接口定义了两个方法: StartAsync(CancellationT ...
- ASP.NET Core 2.2 基础知识(八) 主机 (未完待续)
主机负责应用程序启动和生存期管理.共有两个主机 API : 1.Web 主机 : 适用于托管 Web 应用,基于 IWebHostBuilder ; 2.通用主机 : 适用于托管非 Web 应用. 基 ...
随机推荐
- Hello to the cruel world
- 如何最快地实现 ALTER TABLE
如果您不了解ALTER TABLE的语法,可以先参考: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html 使用ALTER TABLE 可以 ...
- ng4转义html
https://stackoverflow.com/questions/31548311/angular-html-binding <div [innerHTML]="content& ...
- 怎么把linux的磁盘映射到windows上
步骤如下: 右击如下的computer: 然后选择:Map network drive... 然后在下图按图中所示操作: 最后成功如下图所示:
- Python之日志操作(logging)
import logging 1.自定义日志级别,日志格式,输出位置 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s | ...
- Hibernate中inverse、cascade的说明
一: 前沿:刚刚学习hibernate时,对于inverse很是纠结,不知道什么时候该用什么时候不该用,在网上找了一些资料,说的也很含糊,我都不知道如果写了"inverse=true&quo ...
- Nginx各项配置的含义
#user nobody; #配置用户或者组,默认为nobody nobody worker_processes 4; #允许生成的进程数,默认为1 worker_cpu_affinity 00000 ...
- react+webpack+babel+eslint+redux+react-router+sass 环境快速搭建
本文中的例子支持webpack-dev-server自动刷新及react热替换,使用了redux管理state,用react-router切换路由,用babel实现ES6语法书写,同时支持async/ ...
- 原型和JS内置对象
原型 1.定义 每一个对象都有原型 原型仍然是一个对象 模拟实现面向对象的继承性 2.原型链 对象的原型还有原型 对象除了可以使用自有属性还可以继承原型上的属性 3.获取原型 对象.__proto__ ...
- JavaScript秘密花园
译文地址 bonsaiden.github.io/JavaScript-Garden/zh/#intro.authors 之前被人问到JS一些概念性的东西,感觉很模糊,可能层次比较浅,偏理论的东西实践 ...