SignalR介绍

SignalR介绍来源于微软文档,不过多解释。https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-2.1

ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程。 实时 Web 功能使服务器端代码能够即时将内容推送到客户端。

SignalR 的适用对象:

  • 需要来自服务器的高频率更新的应用。 例如:游戏、社交网络、投票、拍卖、地图和 GPS 应用。
  • 仪表板和监视应用。 示例包括公司仪表板、销售状态即时更新或行程警示。
  • 协作应用。 协作应用的示例包括白板应用和团队会议软件。
  • 需要通知的应用。 社交网络、电子邮件、聊天、游戏、行程警示以及许多其他应用都使用通知。

以下是 ASP.NET Core SignalR 的一些功能:

  • 自动管理连接。
  • 同时向所有连接的客户端发送消息。 例如,聊天室。
  • 将消息发送到特定的客户端或客户端组。
  • 扩展以处理增加的流量。

以上是SignalR介绍,除了以上说明外还有如下优点:

  • 它可支持各个平台通信。只要可以使用websocket就可以进行连接。
  • 而且进行了大量优化处理,非常方便开发者使用。
  • 拥有自由可扩展性,可通过redis 方式搭建分布式socket通信,支持成千上万人不是梦。
  • 自定义协议,除了json协议外、还支持MessagePack协议。还可以自己定义相关协议进行扩展。
  • 可以用于unity、Layair、白鹭引擎、大数据分析平台等高频率使用消息实时通信器。

SignalR使用

一、  新建项目,新建一个空Asp.net core 网站

二、引用SignalR中间件

1. 创建Hub中间件 HubHelper,及游戏简单处理逻辑类

using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Timers; /// <summary>
/// 消息中心
/// </summary>
public class HubHelper : Hub
{
/// <summary>
/// 游戏逻辑
/// </summary>
static GameLogic gameLogic;
static bool isStart = false; /// <summary>
/// 获取当前用户Id
/// </summary>
/// <param name="data"></param>
public void GetId(Data data)
{
Clients.Caller.SendAsync("GetId", Context.ConnectionId);
}
/// <summary>
/// 获取当前连接所有用户
/// </summary>
/// <param name="data"></param>
public void GetALLUser(Data data)
{
if (gameLogic != null)
Clients.Caller.SendAsync("GetALLUser", gameLogic.list);
}
/// <summary>
/// 用户状态改变
/// </summary>
/// <param name="user">用户信息</param>
public void UpdateSate(UserInfo user)
{
gameLogic.UpdateUserInfo(Context.ConnectionId, user);
}
/// <summary>
/// 用户加入
/// </summary>
/// <param name="data"></param>
public void Join(Data data)
{
if (!isStart)
{
isStart = true;
gameLogic = new GameLogic(this.Clients.All);
}
gameLogic.JoinUser(this.Context.ConnectionId, data); } /// <summary>
/// 用户断开
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
public override Task OnDisconnectedAsync(Exception exception)
{
if (gameLogic != null)
gameLogic.LevelUser(Context.ConnectionId);
return base.OnDisconnectedAsync(exception);
}
}
/// <summary>
/// 游戏逻辑
/// </summary>
public class GameLogic
{
/// <summary>
/// 全局客户端通信信息
/// </summary>
readonly IClientProxy gloable;
/// <summary>
/// 游戏定时器
/// </summary>
readonly Timer gameTimer;
/// <summary>
/// 所有用户
/// </summary>
public List<UserInfo> list = new List<UserInfo>(); public GameLogic(IClientProxy _gloable)
{
gloable = _gloable;
//启动模拟游戏帧
gameTimer = new Timer();
gameTimer.Elapsed += GameTimer_Elapsed;
gameTimer.Start();
} private void GameTimer_Elapsed(object sender, ElapsedEventArgs e)
{
for (int i = ; i < list.Count; i++)
{
var item = list[i];
//发送已改变状态用户信息广播
if (item.Change)
{
item.Change = false;
gloable.SendAsync("update", list[i]);
}
}
}
/// <summary>
/// 用户加入
/// </summary>
/// <param name="id">用户编号</param>
/// <param name="data">加入信息</param>
public void JoinUser(string id, Data data)
{
//随机获取角色图片
var user = new UserInfo() { Id = id, Name = data.Name, Role = "role" + new Random().Next(, ) + ".jpg", Change = true };
list.Add(user);
gloable.SendAsync("add", user);
}
/// <summary>
/// 用户断开处理
/// </summary>
/// <param name="id">用户编号</param>
public void LevelUser(string id)
{
var user = list.FirstOrDefault(mm => mm.Id == id);
if (user != null)
{
gloable.SendAsync("level", user);
list.Remove(user);
}
}
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="id">用户编号</param>
/// <param name="p">用户信息</param>
public void UpdateUserInfo(string id, UserInfo changeUser)
{
var user = list.FirstOrDefault(mm => mm.Id == id);
if (user != null)
{
user.X = changeUser.X;
user.Y = changeUser.Y;
user.Change = true;
}
}
}
/// <summary>
///用户信息
/// </summary>
public class UserInfo
{
public string Id { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 用户角色图片
/// </summary>
public string Role { get; set; }
public int X { get; set; }
public int Y { get; set; }
/// <summary>
/// 是否动作变化
/// </summary>
public bool Change { get; set; }
}
/// <summary>
/// 传输数据
/// </summary>
public class Data
{
public string Name { get; set; }
public string Value { get; set; }
}

2. 注册SignalR中间件,注册文件浏览。

    public class Startup
{ public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseDefaultFiles().UseStaticFiles();
app.UseSignalR(router => {
router.MapHub<HubHelper>("/game");
});
}
}

三、前端代码部分

1.实现 MSGGame.js 游戏消息处理js, 重写原因是:无代码提示,而且重写后方便自己扩展增加功能和相关管理。NetCore SingalR无重连功能,需要自己实现。

//消息处理
var MSG = {
isStart: false,
connection: null, /**
* 初始化信息处理 返回promis
* @param {string} _url 消息地址
* @param {Function} _func 相关绑定函数
*/
init: function (url) {
if (url == null)
url = "/game";
MSG.connection = new signalR.HubConnectionBuilder().withUrl(url).build();
},
/**
* 注册监听函数
* @param {any} key 监听键名
* @param {any} func 监听执行函数
*/
reg: function (key,func) {
MSG.connection.on(key, function (result) {
func(result);
});
},
/**启动消息 返回promis*/
start: function () {
if (MSG.isStart) {
return;
}
MSG.isStart = true;
var _result = MSG.connection.start();
_result.then(function (_return) { }).catch(function (err) {
MSG.isStart = false;
return console.error(err.toString());
});
return _result;
}, /**
* 停止消息 返回promis
* */
stop: function () {
if (!MSG.isStart) {
return;
}
var _result = MSG.connection.stop();
_result.then(function (_return) { }).catche(function (err) { });
MSG.isStart = false;
return _result;
},
/**
*
* @param {any} api
* @param {any} msg
*/
send: function (api, msg) {
if (!MSG.isStart) {
return;
}
var _result = MSG.connection.invoke(api, msg);
//回调处理
_result.then(function (_return) { });
//错误处理
_result.catch(function (_error) { });
return _result;
},
/**重新连接 未实现
*@param {number} num 尝试连接次数
*/
reconnection: function (num) {
if (MSG.isStart) { }
}
};

2.在wwwroot下建立index.html 然后编写简单逻辑

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
body {
position: relative;
} .role {
position: absolute;
} .role, img {
width: 150px;
height: 150px;
} .role > p {
position: absolute;
bottom: ;
left: ;
background: rgba(, , , 0.73);
color: red;
overflow: hidden;
text-align: center;
width: %;
} #content {
width: 200px;
height: 200px;
overflow-y: scroll
}
</style>
</head> <body>
<div>
<div id="clone_role" class="role" style="display: none;">
<p>克隆对象</p>
<img src="role1.jpg" />
</div>
<input type="text" name="name" id="userName" placeholder="你的名称!" />
<button id="sendButton">开始测试</button>
<div id="content">
输入名称,点击开始进行测试。随后随便点击屏幕。
</div>
</div>
<script src="jquery-1.10.2.min.js"></script>
<script src="signalr.min.js"></script>
<script src="game.js"></script>
<script>
$(function () {
var content = document.getElementById("content");//内容信息
var $body = $(document.body);//body容器
var userArray = new Array();//所有用户
var userPostion = { id: "", name: "", x: , y: , start: false }; //本人信息
var GameMain = {
//加载所有监听事件
load: function () {
//状态更新
MSG.reg("update", function (result) {
var user = userArray[result.id];
if (user) {
user.img.style.left = result.x + "px";
user.img.style.top = result.y + "px";
}
});
//获取编号
MSG.reg("GetId", function (result) {
userPostion.id = result;
});
//获取当前连接所有用户
MSG.reg("GetALLUser", function (result) {
if (result) {
for (var i = ; i < result.length; i++) {
GameMain.joinUser(result[i]);
}
}
});
//用户加入
MSG.reg("add", function (result) {
content.innerText += result.name + " :用户加入";
GameMain.joinUser(result);
});
//用户离开
MSG.reg("level", function (result) {
content.innerText += result.name + ":离开";
GameMain.levelUser(result);
});
},
//用户加入展示
joinUser: function (user) {
userArray[user.id] = user;
//克隆模板
var clone = $("#clone_role").clone();
clone.children("img").attr("src", user.role);
clone.children("p").text(user.name);
userArray[user.id].img = clone[];
$body.append(userArray[user.id].img);
clone.slideDown();
},
//用户离开
levelUser: function (p) {
var user = userArray[p.id];
if (user) {
document.body.removeChild(user.img);
userArray[p.id] = undefined;
}
},
//系统事件
sysEvent: function () {
//点击发送坐标
$(document).click(function (e) {
userPostion.x = e.clientX;
userPostion.y = e.clientY;
if (userPostion.start) {
MSG.send("UpdateSate", userPostion);
}
})
//点击发送加入房间信息
$("#sendButton").click(function () {
if (MSG.isStart && !userPostion.start) {
var userName = $("#userName").val();
MSG.send("Join", { name: userName, value: "" });
userPostion.start = true;
}
})
}
}; //初始化函数
MSG.init("game");
//加载消息监听及系统事件
GameMain.load();
GameMain.sysEvent();
//启动消息
MSG.start().then(function () {
MSG.send("GetId", { name: "", value: "" });
MSG.send("GetALLUser", { name: "", value: "" });
});
})
</script>
</body>
</html>

3. 最终目录结构为:

四、运行测试,打开多个网页。输入相关名称。然后点击屏幕。看看是否能联动。 可以发给自己好朋友测测看看。

五、Signalr问题说明、相关建议经验

1.Signalr 发布到 winserver 2008R2 时 无法使用websocket通信,需要进行特殊处理。

2.对于实时性要求非常高时,没有进行高并发处理过。希望处理过的人,通知我下。

3.我这有白鹭引擎、Layaair 连接Signalr 的TS代码, 也有unity 连接 net core Signalr 代码(因 unity  我用时只提供了 老版本连接方法,现在没去看是否有新可用的), 需要的可以联系我。

4. Net Core 开源后,群众呼声很高。无论是机器学习、微服务方面 微软都在逐步大力支持中, 希望大家共同努力让.Net 这么好用的东西 走得更远。

5.曾经不写博客什么的感觉没用,不过眼看.net 人员越来越少。    感叹!

6.如果想实现分布式的可参考官网,自己动手丰衣足食。

以上仅供娱乐测试。代码地址:https://github.com/840900649/SignalRTest

Net Core SignalR 测试,可以用于unity、Layair、白鹭引擎、大数据分析平台等高可用消息实时通信器。的更多相关文章

  1. Dubbo入门到精通学习笔记(十五):Redis集群的安装(Redis3+CentOS)、Redis集群的高可用测试(含Jedis客户端的使用)、Redis集群的扩展测试

    文章目录 Redis集群的安装(Redis3+CentOS) 参考文档 Redis 集群介绍.特性.规范等(可看提供的参考文档+视频解说) Redis 集群的安装(Redis3.0.3 + CentO ...

  2. [asp.net core]SignalR一个例子

    摘要 在一个后台管理的页面想实时监控一些操作的数据,想到用signalR. 一个例子 asp.net core+signalR 使用Nuget安装包:Microsoft.AspNetCore.Sign ...

  3. ASP.NET Core SignalR:基础概述

    一.简介 ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程. 实时 Web 功能使服务器端代码能够即时将内容推送到客户端. SignalR 的适用 ...

  4. Asp.Net Core SignalR 系列博客

    系列 SignalR+Vue SignalR+Vue 服务端向客户端发送信息 SignalR+Vue+Log4net 实时日志推送 待定...... 源码地址:https://github.com/Q ...

  5. .net core signalR 服务端强制中断用户连接

    .net core signalR 服务端断开连接 { } { } *:first-child { } *:last-child { } { } { } { } { } { } { } { } { } ...

  6. ASP.NET Core SignalR中的流式传输

    什么是流式传输? 流式传输是这一种以稳定持续流的形式传输数据的技术. 流式传输的使用场景 有些场景中,服务器返回的数据量较大,等待时间较长,客户端不得不等待服务器返回所有数据后,再进行相应的操作.这时 ...

  7. Asp.Net Core SignalR 用泛型Hub优雅的调用前端方法及传参

    继续学习 最近一直在使用Asp.Net Core SignalR(下面成SignalR Core)为小程序提供websocket支持,前端时间也发了一个学习笔记,在使用过程中稍微看了下它的源码,不得不 ...

  8. Asp.Net Core SignalR 与微信小程序交互笔记

    什么是Asp.Net Core SignalR Asp.Net Core SignalR 是微软开发的一套基于Asp.Net Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给 ...

  9. ASP.NET Core SignalR

    ASP.NET Core SignalR 是微软开发的一套基于ASP.NET Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给Web客户端. 功能 自动管理连接 允许同时广播 ...

随机推荐

  1. 使用jQuery可能出现的错误

  2. GridView上同时定义了 DataSource 和 DataSourceId

    VS平台下ASP.NET网站的建立,我们常常要跟数据库打交道,获取数据库的信息,通过GridView控件进行显示,需要为GridView指定 DataSourceId或者DataSource,切忌不可 ...

  3. Broadcast总结 service

    有时候离开应用就会接收不到系统的广播是因为系统默认发送的广播都会有一个参数 ntent startIntent = new Intent();startIntent.putExtra("pk ...

  4. win下安装composer

    1.在官网上下载composer的安装程序. https://getcomposer.org/ 2.双击运行Composer-Setup.exe程序,选择你自已的php安装目录打到php.exe.   ...

  5. windows下 Memcache cpu占用过高

    分析应该是memcache的内存大小还是默认配置,已经满足不了当前的大数据量的需要了,大量的新缓存需要进入,同时大量的旧缓存又需要被淘汰出来,一进一出导致CPU占用过多. 进入注册表,找到:HKEY_ ...

  6. vim之quickfix

    [vim之quickfix] quickfix功能将编译过程中产生的错误信息保存到文件中,然后vim利用这些信息跳转到源文件的对应位置,我们就可以进行错误的修正,之后跳到下一个错误重复上述操作,从而极 ...

  7. 用java创建UDF,并用于Hive

    典型代码如下: 导入UDF类: import org.apache.hadoop.hive.ql.exec.UDF; public class UpperCassUDF extends UDF{ pu ...

  8. 品味性能之道<五>:SQL分析工具

    一.SQL语句到底是怎么执行的? 想了解SQL语句到底是怎么执行的,那就需要进行SQL语句执行计划分析. 那什么是SQL语句执行计划呢? 就是Oracle服务器执行SQL语句的过程.例如确定是否使用索 ...

  9. 2018.10.20 NOIP模拟 面包(数学期望)

    传送门 把方差的式子拆开. 方差=平方的期望-期望的平方. 显然只用维护点对的个数和总方案数就行了. 利用分步的思想来统计. 要统计覆盖一个矩形(x1,y1,x2,y2)(x1,y1,x2,y2)(x ...

  10. 2018.08.19 NOIP模拟 dp(二分+状压dp)

    Dp 题目背景 SOURCE:NOIP2015-SHY-10 题目描述 一块土地有 n 个连续的部分,用 H[1],H[2],-,H[n] 表示每个部分的最初高度.有 n 种泥土可用,他们都能覆盖连续 ...