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客户端. 功能 自动管理连接 允许同时广播 ...
随机推荐
- 根据二进制和十进制转换规则转换成游戏[xyytit]
摘要: 二進位是由十進位轉換而成,它的數字都由1.0組成的.我們研究發現由十進位轉換而成的二進位的數字可以不只局限在於1~127,它的數可以更加深加廣,並且可以利用二進位的規則轉換成遊戲.我們利用2n ...
- c++泛型模板
模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数.返回值取得任意类型. 模板是一种对类型进行参数化的工具: 通常有两种形式:函 ...
- IBM MQ 学习
import java.io.IOException; import java.util.HashMap; import java.util.Map; import com.ibm.mq.MQC; i ...
- 在java工程中导入jar包的注意事项
在java工程中导入jar包后一定要bulid path,不然jar包不可以用.而在java web工程中导入jar包后可以不builld path,但最好builld path.
- Scrum使用心得 【转】
原文链接: http://blog.sina.com.cn/s/blog_58db96bc0100ymuk.html 1 Scrum管理模式和传统管理模式的区别 这些管理模式本质上目的相同: ...
- SVN版本冲突中 Files 的值“ < < < < < < < .mine”无效路径中具有非法字符的解决办法
.NET 中 SVN版本冲突中 Files 的值“ < < < < < < < .mine”无效路径中具有非法字符的解决办法: 一. 1.将项目逐个进行编译, ...
- dedecms目录说明
1.有多个common.inc.php文件,注意引入的是哪一个,引入以后,里面的常量才可以用: 2.路径向上跳转 require_once('../../plus/phpexcel/PHPExcel. ...
- 电商类Web原型制作分享-IKEA
IKEA是一个家居整合大型零售商,属于电商类官网.电商以展示商品.售后服务.购物流程为主.根据网站的图文方式排版,主导航栏使用的标签组,区域导航栏使用的是垂直选项卡,实现下拉弹出面板交互的功能. 本原 ...
- Android无线调试(转)
Android无线调试——抛开USB数据线 开发Android的朋友都知道,真机调试需要把手机与PC相连,然后把应用部署到真机上进行安装和调试.长长的USB线显得很麻烦,而且如果需要USB接口与其他设 ...
- spring mvc 静态资源版本控制
spring bean 文件中增加 <bean class="cn.zno.smse.common.context.VersionServletContext">< ...