+
95
-

回答

SignalR是一个net上开源的库,跨平台;让Web应用与其他应用通讯变得很简单,Web服务端可以实时的将内容推送给对应的客户端,客户端发送的信息也可以实时到其他客户端。

SignalR提供了一种远程过程调用(RPC)的方式,使得客户端可以调用服务器的方法,同样在服务器端的方法中也能调用客户端的方法。

SignalR的通信方式

SignalR支持如下的方式实现实时通信:

WebSockets:是一种在单个TCP连接上进行全双工通信的协议,使得服务器和浏览器的通信更加简单,服务端可以主动发送信息。

Server-Sent Events:SSE 与 WebSocket 作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。WebSocket是双向的,而SSE是单向的。

Long Polling(长轮询) :和传统的轮询原理一样,只是服务端不会每次都返回响应信息,只有有数据或超时了才会返回,从而减少了请求次数。

SignalR会自动选择服务器和客户端能力范围内的最佳通信方式(是不是很优秀) ,当然也可以手动指定。

SignalR的应用场景

其实对于Web模式下的实时通信,SignalR用上试试,感觉还是很给力的。

服务端主动推送信息;比如发送公告场景;

监控或看板数据实时显示;比如监控系统实时展示分布到各个客户端上的数据;

服务端和客户端交互;比如客服系统的聊天场景。

理论大概先说这么多,接下来就用实例演示一波。

具体代码:

开始之前,还需要了解RPC和Hub的概念。

RPC:全程Remote Procedure Call,字面意思远程服务调用,可以像调用本地方法一样调用远程服务。前端可以调用后端方法,后端也可以调用前端方法。

Hub:基于RPC,接受从客户端发过来的消息,也同时负责把服务端的消息发送给客户端。客户端可以调用Hub里面的方法,服务端可以通过Hub调用客户端里面的方法。

好了,概念已经理解清楚了,接下来上代码。

在项目里新增Hub类:

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRDemo.Server
{
public class SignalRHub : Hub
{
/// <summary>
/// 客户连接成功时触发
/// </summary>
/// <returns></returns>
public override async Task OnConnectedAsync()
{
var cid = Context.ConnectionId;

//根据id获取指定客户端
var client = Clients.Client(cid);

//向指定用户发送消息
await client.SendAsync("Self", cid);

//像所有用户发送消息
await Clients.All.SendAsync("AddMsg", $"{cid}加入了聊天室");
}
}
}

为了让外部可以访问,我们还需要一个控制器。在控制器里声明随便建一个:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using SignalRDemo.Server;
using System.Threading.Tasks;

namespace SignalRDemo.Controllers
{
public class HomeController : Controller
{
private readonly IHubContext<SignalRHub> _countHub;

public HomeController(IHubContext<SignalRHub> countHub)
{
_countHub = countHub;
}

/// <summary>
/// 发送信息
/// </summary>
/// <param name="msg"></param>
/// <param name="id"></param>
/// <returns></returns>
public async Task Send(string msg, string id)
{
await _countHub.Clients.All.SendAsync("AddMsg", $"{id}:{msg}");
}
}
}
再然后进入StartUp设置端点:

endpoints.MapHub<SignalRHub>("/hub");

完成以后,配置signalr客户端:
setupConn = () => {
conn = new signalR.HubConnectionBuilder()
.withUrl("/hub")
.build();

conn.on("AddMsg", (obj) => {
$('#msgPanel').append(`<p>${obj}</p>`);
});

conn.on("Finished", () => {
conn.stop();
$('#msgPanel').text('log out!');
});

conn.on("Self", (obj) => {
$('#userId').text(obj);
});

conn.start()
.catch(err => console.log(err));
}

要注意withUrl里面的路径就是之前设置好的端点。

运行效果:

800_auto

Hub还支持组操作,比如:

//将用户添加到A组
await Groups.AddToGroupAsync(Context.ConnectionId, "GroupA");
//将用户踢出A组
await Groups.RemoveFromGroupAsync(Context.ConnectionId, "GroupA");
//向A组所有成员广播消息
await Clients.Group("GroupA").SendAsync("AddMsg", "群组消息");


网友回复

我知道答案,我要回答