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

时间:2022-09-16 08:38:32

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 网站

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

二、引用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. 最终目录结构为:

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

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

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

五、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&plus;CentOS)、Redis集群的高可用测试(含Jedis客户端的使用)、Redis集群的扩展测试

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

  2. &lbrack;asp&period;net core&rsqb;SignalR一个例子

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

  3. ASP&period;NET Core SignalR:基础概述

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

  4. Asp&period;Net Core SignalR 系列博客

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

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

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

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

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

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

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

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

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

  9. ASP&period;NET Core SignalR

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

随机推荐

  1. 通俗易懂地讲解TCP建立连接的三次握手和释放连接的四次挥手

    TCP建立连接时,为什么要进行三次挥手? 每一次TCP连接都需要三个阶段:连接建立.数据传送和连接释放.三次握手就发生在连接建立阶段. 在谢希仁著<计算机网络>第四版中讲三次握手的目的是为 ...

  2. 【Window】Tor(洋葱头路由)&plus;Privoxy 网络实践(附带Java实例代码)

    1.背景 平时我们需要访问onion后缀的网站,需要通过Tor(The Onion Router,洋葱路由器).一般来说安装Tor Broswer就可以满足需要.但是项目我要做的是通过程序来获取oni ...

  3. CSS各个浏览器Hack的写法

    Hack是针对不同的浏览器去写不同的CSS样式,从而让各浏览器能达到一致的渲染效果,那么针对不同的浏览器写不同的CSS CODE的过程,就叫CSS HACK,同时也叫写CSS Hack.然后将Hack ...

  4. 笔记整理--C语言

    linux下错误的捕获:errno和strerror的使用 - Google Chrome (2014/2/26 17:31:39) linux下错误的捕获:errno和strerror的使用 201 ...

  5. 【Ubuntu 16】DEB软件包管理

    一.背景介绍 开源软件最早的时候没有软件包和软件包管理器,用户只能下载源码包自行配置 编译 安装. 后来linux各发行版本推出了软件包格式和软件包管理程序 Red Hat.Centos使用RPM格式 ...

  6. UITableView设置单元格选中后只显示一个打勾的三种简单方法(仅供参考)

    1.第一种方法:先定位到最后一行,若选中最后一行直接退出,否则用递归改变上次选中的状态,重新设置本次选中的状态. - (UITableViewCell*)tableView:(UITableView* ...

  7. Java并发程序设计(五)JDK并发包之线程复用:线程池

    线程复用:线程池 一.为什么需要线程池 为了避免系统频繁地创建和销毁线程,使用线程池让线程进行复用.(即创建线程变成了从线程池中获取空闲线程,销毁线程变成了把线程放回线程池中.) 二.JDK对线程池的 ...

  8. Ural 1297 Palindrome(后缀数组&plus;最长回文子串)

    https://vjudge.net/problem/URAL-1297 题意: 求最长回文子串. 思路: 先将整个字符串反过来写在原字符串后面,中间需要用特殊字符隔开,那么只需要某两个后缀的最长公共 ...

  9. SHA1WithRSA

    SHA1WithRSA:用SHA算法进行签名,用RSA算法进行加密.   算法说明: 在对进行SHA1算法进行签名后,要求对签名后的数据进行处理,而不是直接进行RSA算法进行加密. 要求把SHA1签名 ...

  10. BZOJ4033:&lbrack;HAOI2015&rsqb;树上染色——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4033 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将 ...