SingalR的简单认识
SingalR的简单认识
什么是 SignalR?
ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能。 实时 web 功能使服务器端代码可以立即将内容推送到客户端。
适用于 SignalR 的场景:
- 需要从服务器进行高频率更新的应用。 示例包括游戏、社交网络、投票、拍卖、地图和 GPS 应用。
- 仪表板和监视应用。 示例包括公司仪表板、即时销售更新或旅行警报。
- 协作应用。 协作应用的示例包括白板应用和团队会议软件。
- 需要通知的应用。 社交网络、电子邮件、聊天、游戏、旅行警报和很多其他应用都需使用通知。
Asp.net SignalR 2 实现 服务端消息推送到Web端, 更加简单. 为了获取更好的可伸缩性, 我们引入消息队列, 看如下基本流程图:
消息队列MQ监听, 在Web site 服务端一收到消息,马上通过Signalr 推送广播到客户端.
使用步骤
具体操作步骤:
以实现消息推送为示例
步骤一:
安装
Install-Package Microsoft.AspNet.SignalR
步骤二:
UPDATE-Package Microsoft.AspNet.SignalR -Version 2.4.0
UPDATE-Package jQuery -Version 1.8.2
步骤三:
创建一个集线器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
//先在Nuget上搜索Microsoft.AspNet.SignalR安装
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace SignalRDEMO
{
/// <summary>
/// 自定义SignalR集线器代理类名称
/// </summary>
[HubName("myChatHub")]
public class MyChatHub : Hub
{
/// <summary>
/// 推送至所有客户端
/// </summary>
/// <param name="message">消息</param>
public void Send(string message)
{
//调用所有客户端的SendMessage方法
Clients.All.SendMessage(message);
}
}
}
步骤四:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>SignalR实时消息推送到客户端</title>
<script src="Scripts/jquery-1.8.2.js"></script>
<!--引用SignalR库-->
<script src="Scripts/jquery.signalR-2.1.2.min.js"></script>
<!--引用自动生成的SignalR集线器(Hub)脚本.在运行的时候在浏览器的Source下可看到-->
<script src="/signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
//引用服务端的集线器代理类
var chat = $.connection.myChatHub;
//定义服务器端调用的客户端SendMessage方法来显示新消息
chat.client.SendMessage = function (message) {
ShowMessage(message);
};
//$.extend(chat.client, {
// SendMessage: function (message) {
// ShowMessage(message);
// }
//});
//设置焦点到输入框
$('#message').focus();
//开始连接服务器
$.connection.hub.start().done(function () {
$('#SendMessage').click(function () {
//调用服务器端定义的Send方法
chat.server.send($('#message').val());
//清空输入框信息并获取焦点
$('#message').val('').focus();
});
});
});
//向页面添加消息
function ShowMessage(message) {
$('#list').append('<li>' + message + '</li>');
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="text" id="message" />
<input type="button" id="SendMessage" value="发送" />
<ul id="list">
</ul>
</div>
</form>
</body>
</html>
步骤五:
添加启动类StartUp
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SignalRChat.Startup))]
namespace SignalRChat
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Any connection or hub wire up and configuration should go here
app.MapSignalR();
}
}
}
说明:
每一个使用的OWin组件的Web框架都需要一个StartUp入口类,用来声明OWin组件:
-
项目会自动扫描程序集根下的名为StartUp的类作为入口类
-
通过添加 [assembly: OwinStartup(typeof(SignalRDEMO.Startup))] 标签标记入口类
SingalR常用的推送方式
以下列出其他推送方式:
-
所有连接的客户端
Clients.All.show(content); -
仅调用的客户端
Clients.Caller.show(content); -
除调用客户端之外的所有客户端
Clients.Others.show(content); -
特定的客户端标识的连接 id
Clients.Client(Context.ConnectionId).show(content); -
所有连接的客户端除外指定客户端,由连接 ID 标识
Clients.AllExcept(connectionId1, connectionId2).show(content); -
指定组中的所有连接的客户端
Clients.Group(groupName).show(content); -
指定组中的所有连接的客户端除外指定客户端,由连接 ID 标识。
Clients.Group(groupName, connectionId1, connectionId2).show(content); -
所有连接的客户端指定组中除调用客户端
Clients.OthersInGroup(groupName).show(content); -
所有客户端和组列表中的连接 Id
Clients.Clients(ConnectionIds).show(content); -
组的列表。
Clients.Groups(GroupIds).show(content); -
按名称的用户
Clients.Client(username).show(content); //这里的username我还没理解是怎么创建的 -
(在 SignalR 2.1 中引入) 的用户名称的列表。
Clients.Users(new string[] { “myUser”, “myUser2” }).show(content)
这里关于ConnectionId做一下解释
每个连接的页面都会产生不同的连接id,并且这个连接id是随机产生,不能自定义的
集线器中为我们提供了Context对象可以获取到这个连接id,这里的id也就相当于用于验证身份的t唯一token一样。
/// <summary>
/// 返回每个连接的id
/// </summary>
public void ReturnConnectionId()
{
Clients.Caller.show(Context.ConnectionId);
}
//定义推送,返回各个客户端连接
$.connection.hub.start()
.done(function () {
$("#btn_sendConnectionId").click(function () {
chat.server.returnConnectionId(); //将客户端的content内容发送到服务端
});
});
下面简单举一个应用SingalR的例子:
这里假设张三发送消息到服务器:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="Scripts/jquery-3.4.1.min.js"></script>
<script src="Scripts/jquery.signalR-2.2.2.min.js"></script>
<script src="/signalr/hub/hubs"></script>
<meta charset="utf-8" />
<style type="text/css">
body {
margin: 20px;
}
.input {
padding-left: 5px;
}
</style>
</head>
<body>
<div>
<h4>我是张三</h4>
<p>
<input type="text" id="content" placeholder="" class="input" /> <input type="button" value="发送给李四" class="btn btn-sm btn-info" id="btn_send" />
</p>
<div>
<h4>接收到的信息:</h4>
<ul id="dataContainer">
</ul>
</div>
</div>
<script language="javascript">
$(function() {
var chat = $.connection.myChatHub; //连接服务端集线器,de*b为服务端集线器名称,js上首字母须改为小写(系统默认)
//定义客户端方法,此客户端方法必须与服务端集线器中的方法名称、参数均一致。
//实际上是服务端调用了前端的js方法(订阅)
$.connection.hub.qs = { 'userName': '张三' }
chat.client.show=function(content) {
var html = '<li>' + htmlEncode(content) + "</li>";
$("#dataContainer").append(html);
}
//定义推送
$.connection.hub.start()
.done(function() {
$("#btn_send").click(function() {
chat.server.callOne("李四",$("#content").val()); //将客户端的content内容发送到服务端
$("#content").val("");
});
});
});
//编码
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
</body>
</html>
这里是李四发送消息:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="Scripts/jquery-3.4.1.min.js"></script>
<script src="Scripts/jquery.signalR-2.2.2.min.js"></script>
<script src="/signalr/hub/hubs"></script>
<meta charset="utf-8" />
<style type="text/css">
body {
margin: 20px;
}
.input {
padding-left: 5px;
}
</style>
</head>
<body>
<div>
<h4>我是李四</h4>
<p>
<input type="text" id="content" placeholder="" class="input" /> <input type="button" value="发送给张三" class="btn btn-sm btn-info" id="btn_send" />
</p>
<div>
<h4>接收到的信息:</h4>
<ul id="dataContainer"></ul>
</div>
</div>
<script language="javascript">
$(function() {
var chat = $.connection.myChatHub; //连接服务端集线器,de*b为服务端集线器名称,js上首字母须改为小写(系统默认)
//定义客户端方法,此客户端方法必须与服务端集线器中的方法名称、参数均一致。
//实际上是服务端调用了前端的js方法(订阅)
$.connection.hub.qs = { 'userName': '李四' }
chat.client.show=function(content) {
var html = '<li>' + htmlEncode(content) + "</li>";
$("#dataContainer").append(html);
}
//定义推送
$.connection.hub.start()
.done(function() {
$("#btn_send").click(function() {
chat.server.callOne("张三", $("#content").val()); //将客户端的content内容发送到服务端
$("#content").val("");
});
});
});
//编码
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
</body>
</html>
这里是服务端代码:
/// <summary>
/// 发送给指定连接
/// </summary>
/// <param name="toName"></param>
/// <param name="content"></param>
public void CallOne(string toName, string content)
{
//根据username获取对应的ConnectionId
var connectionId = HttpContext.Current.Application[toName].ToString();
Clients.Client(connectionId).show(content);
}
/// <summary>
/// 初次连接
/// </summary>
/// <returns></returns>
public override Task OnConnected()
{
string username = Context.QueryString["userName"]; //获取客户端发送过来的用户名
string connectionId = Context.ConnectionId;
HttpContext.Current.Application.Add(username, connectionId); //存储关系
return base.OnConnected();
}
简单实现了张三和李四两个人的实时通讯,可以看出,利用了SingalR,比使用WebSocket来说要简单很多。
乾坤未定,你我皆是黑马!!!
上一篇: 图的简单认识
下一篇: Android实现动态定值范围效果的控件