我一直觉得学习的最好方法就是先让程序能够正常运行,才去学习他的原理,剖析他的细节.

就好像这个图:

所以,我们先跟着官方文档,创建一个 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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
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 支持几种方法用于处理实时通信:

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 概述的更多相关文章

  1. ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述

    为了方便演示,以 .NET Core 控制台应用程序讲解. 我们新建一个控制台应用程序,安装 "Newtonsoft.Json" Nuget 包,然后右键点击该项目,选择" ...

  2. ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 请求

    可以注册 IHttpClientFactory 并将其用于配置和创建应用中的 HttpClient 实例. 这能带来以下好处: 提供一个中心位置,用于命名和配置逻辑 HttpClient 实例. 例如 ...

  3. ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)

    要啥自行车,直接看手表 //返回基元类型 public string Get() { return "hello world"; } //返回复杂类型 public Person ...

  4. ASP.NET Core 2.2 基础知识(十) Web服务器 - Kestrel

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  5. ASP.NET Core 2.2 基础知识(十五) Swagger

    安装 Nuget 包 注册 Swagger public void ConfigureServices(IServiceCollection services) { services.AddMvc() ...

  6. ASP.NET Core 2.2 基础知识(十三) WebAPI 概述

    我们先创建一个 WebAPI 项目,看看官方给的模板到底有哪些东西 官方给出的模板: [Route("api/[controller]")] [ApiController] pub ...

  7. ASP.NET Core 2.2 基础知识(十一) ASP.NET Core 模块

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  8. ASP.NET Core 2.2 基础知识(九) 使用托管服务实现后台任务

    在 ASP.NET Core 中,后台任务作为托管服务实现.托管服务是一个类,而且必须实现 IHostedService 接口,该接口定义了两个方法: StartAsync(CancellationT ...

  9. ASP.NET Core 2.2 基础知识(八) 主机 (未完待续)

    主机负责应用程序启动和生存期管理.共有两个主机 API : 1.Web 主机 : 适用于托管 Web 应用,基于 IWebHostBuilder ; 2.通用主机 : 适用于托管非 Web 应用. 基 ...

随机推荐

  1. bcc

    #include<bits/stdc++.h> using namespace std; #define mxn 510 struct E{ int from,to; }; int dfn ...

  2. 收藏一个漂亮的Flash焦点图切换

    网上闲逛的时候发现一个Flash焦点图效果,跟喜欢,然后就下载回来,收集在这里,以便以后方便取用.这个Flash使用方法也是相当简单的,如果你喜欢,也可以从这里查看源代码下载. Flash 焦点图效果 ...

  3. HDU 1059 完全背包

    Dividing Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  4. 用静态工厂的方法实例化bean

    //代码如下: package com.timo.domain; public class ClientService { //use static factory method create bea ...

  5. bzoj1914 [Usaco2010 OPen]Triangle Counting 数三角形 计算机和

    [Usaco2010 OPen]Triangle Counting 数三角形 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 526  Solved: 2 ...

  6. How to setup Active Directory (AD) In Windows Server 2016

    Windows Server 2016 is the newest server operating system released by Microsoft in October 12th, 201 ...

  7. CSS属性中cursor:hand

    在 IE 下设置鼠标为手型的方法: cursor: hand,但是在 FIREFOX 中是无效的,解决方法是在FIREFOX中设置: cursor: pointer. 而这个pointer 值在IE和 ...

  8. HDU1869---(最短路+floyd)

    http://acm.hdu.edu.cn/showproblem.php?pid=1869 思路:最短路+floyd 分析:1 题目是要求所有的数据能否满足“六度分离”,那么我们就想到所有点之间的最 ...

  9. mybatis基本流程、jdbc连接、ps:附mybatis(乐观锁)实现

    一.前言 Mybatis和Hibernate一样,是一个优秀的持久层框架.已经说过很多次了,原生的jdbc操作存在大量的重复性代码(如注册驱动,创建连接,创建statement,结果集检测等).框架的 ...

  10. bzoj2002 弹飞绵羊 分块

    这道题是分块的初尝试 讲给定的区间n进行分块处理 这个每次修改的复杂的只有logn 很方便 代码是学黄学长的 http://hzwer.com/3505.html 当然里面还是有一定我自己的想法在里面 ...