Net Core SignalR 测试,可以用于unity、Layair、白鹭引擎、大数据分析平台等高可用消息实时通信器。
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、白鹭引擎、大数据分析平台等高可用消息实时通信器。的更多相关文章
- Dubbo入门到精通学习笔记(十五):Redis集群的安装(Redis3+CentOS)、Redis集群的高可用测试(含Jedis客户端的使用)、Redis集群的扩展测试
文章目录 Redis集群的安装(Redis3+CentOS) 参考文档 Redis 集群介绍.特性.规范等(可看提供的参考文档+视频解说) Redis 集群的安装(Redis3.0.3 + CentO ...
- [asp.net core]SignalR一个例子
摘要 在一个后台管理的页面想实时监控一些操作的数据,想到用signalR. 一个例子 asp.net core+signalR 使用Nuget安装包:Microsoft.AspNetCore.Sign ...
- ASP.NET Core SignalR:基础概述
一.简介 ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程. 实时 Web 功能使服务器端代码能够即时将内容推送到客户端. SignalR 的适用 ...
- Asp.Net Core SignalR 系列博客
系列 SignalR+Vue SignalR+Vue 服务端向客户端发送信息 SignalR+Vue+Log4net 实时日志推送 待定...... 源码地址:https://github.com/Q ...
- .net core signalR 服务端强制中断用户连接
.net core signalR 服务端断开连接 { } { } *:first-child { } *:last-child { } { } { } { } { } { } { } { } { } ...
- ASP.NET Core SignalR中的流式传输
什么是流式传输? 流式传输是这一种以稳定持续流的形式传输数据的技术. 流式传输的使用场景 有些场景中,服务器返回的数据量较大,等待时间较长,客户端不得不等待服务器返回所有数据后,再进行相应的操作.这时 ...
- Asp.Net Core SignalR 用泛型Hub优雅的调用前端方法及传参
继续学习 最近一直在使用Asp.Net Core SignalR(下面成SignalR Core)为小程序提供websocket支持,前端时间也发了一个学习笔记,在使用过程中稍微看了下它的源码,不得不 ...
- Asp.Net Core SignalR 与微信小程序交互笔记
什么是Asp.Net Core SignalR Asp.Net Core SignalR 是微软开发的一套基于Asp.Net Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给 ...
- ASP.NET Core SignalR
ASP.NET Core SignalR 是微软开发的一套基于ASP.NET Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给Web客户端. 功能 自动管理连接 允许同时广播 ...
随机推荐
- 全国省市区数据库SQL(有可能不是最新的)
百度云下载地址:https://pan.baidu.com/s/1lStN7tYpwOtpC-r3G2X2sw
- ECMAScript5之JSON对象属性的遍历顺序
测试浏览器 Chrome.Safari 一 键可以用parseInt解析成整数的,按数值升序顺序. var intObj = { '3.3' : 3.3, '2' : 222, '1' :111 } ...
- 如何在64位WIN7旗舰版下安装SQL2000
1>找到安装包下面的“DEVELOPER”或“ENTERPRISE”等下的X86\SETUP下的“SETUPSQL.EXE”,在安装前右键单击这个文 件, 1.1 打开“兼容性”标签,兼容模式选 ...
- linux下nginx tomcat集群
集群系统一般通过两台或多台节点服务器系统通过相应的硬件及软件互连,每个群集节点都是运行其自己进程的独立服务器. 这些进程可以彼此通信,对网络客户机来说就像是形成了一个单一系统,协同起来向用户提供应用程 ...
- BZOJ 1211[HNOI2004]树的计数 - prufer数列
描述 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi) ...
- swift http post json + 登录
var nsUrl : NSURL = NSURL(string:API_HOST+"/"+LOGIN_API)! var request = NSMutableURLReques ...
- 原生 JS 实现移动端 Touch 滑动反弹
什么是 Touch滑动?就是类似于 PC端的滚动事件,但是在移动端是没有滚动事件的,所以就要用到 Touch事件结合 js去实现,效果如下: 1. 准备工作 什么是移动端的 Touch事件?在移动端 ...
- bitnami redmine svn配置
采用bitnami 方案安装redmine svn服务器端会自己进行安装 1.创建版本库 首先进入remine安装目录的subversion/bin目录,例如我的安装目录是“/opt/redmine/ ...
- DB2 like两个表的字段或like一个变量
DB2中的like的使用是有限制的,它后面不能跟一个变量或者是字段,因此,在存储过程或SQL语句中就不能like一个变量或一个字段. 比如有两个表A(a,b,c,d),B(a,b,c,d). 普遍的用 ...
- 去掉字符串前后的空格和Tab
<script language=Javascript>function String.prototype.Trim() {return this.replace(/(^\s*)|(\s* ...