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; ////// 消息中心 /// public class HubHelper : Hub { /// /// 游戏逻辑 /// static GameLogic gameLogic; static bool isStart = false; /// /// 获取当前用户Id /// /// public void GetId(Data data) { Clients.Caller.SendAsync("GetId", Context.ConnectionId); } /// /// 获取当前连接所有用户 /// /// public void GetALLUser(Data data) { if (gameLogic != null) Clients.Caller.SendAsync("GetALLUser", gameLogic.list); } /// /// 用户状态改变 /// /// 用户信息 public void UpdateSate(UserInfo user) { gameLogic.UpdateUserInfo(Context.ConnectionId, user); } /// /// 用户加入 /// /// public void Join(Data data) { if (!isStart) { isStart = true; gameLogic = new GameLogic(this.Clients.All); } gameLogic.JoinUser(this.Context.ConnectionId, data); } /// /// 用户断开 /// /// /// public override Task OnDisconnectedAsync(Exception exception) { if (gameLogic != null) gameLogic.LevelUser(Context.ConnectionId); return base.OnDisconnectedAsync(exception); } } /// /// 游戏逻辑 /// public class GameLogic { /// /// 全局客户端通信信息 /// readonly IClientProxy gloable; /// /// 游戏定时器 /// readonly Timer gameTimer; /// /// 所有用户 /// public List list = new List (); public GameLogic(IClientProxy _gloable) { gloable = _gloable; //启动模拟游戏帧 gameTimer = new Timer(30); gameTimer.Elapsed += GameTimer_Elapsed; gameTimer.Start(); } private void GameTimer_Elapsed(object sender, ElapsedEventArgs e) { for (int i = 0; i < list.Count; i++) { var item = list[i]; //发送已改变状态用户信息广播 if (item.Change) { item.Change = false; gloable.SendAsync("update", list[i]); } } } /// /// 用户加入 /// /// 用户编号 /// 加入信息 public void JoinUser(string id, Data data) { //随机获取角色图片 var user = new UserInfo() { Id = id, Name = data.Name, Role = "role" + new Random().Next(1, 4) + ".jpg", Change = true }; list.Add(user); gloable.SendAsync("add", user); } /// /// 用户断开处理 /// /// 用户编号 public void LevelUser(string id) { var user = list.FirstOrDefault(mm => mm.Id == id); if (user != null) { gloable.SendAsync("level", user); list.Remove(user); } } /// /// 更新用户信息 /// /// 用户编号 /// 用户信息 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; } } } /// ///用户信息 /// public class UserInfo { public string Id { get; set; } /// /// 用户名 /// public string Name { get; set; } /// /// 用户角色图片 /// public string Role { get; set; } public int X { get; set; } public int Y { get; set; } /// /// 是否动作变化 /// public bool Change { get; set; } } /// /// 传输数据 /// 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("/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 然后编写简单逻辑
"utf-8" /> "clone_role" class="role" style="display: none;">"text" name="name" id="userName" placeholder="你的名称!" />克隆对象
"role1.jpg" />"content"> 输入名称,点击开始进行测试。随后随便点击屏幕。
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