SignalR2.0开发实例之——设置时间、后台其他地方使用集线器、使用自己的连接ID
一、连接的生命周期设置:
如下:
// 该值表示连接在超时之前保持打开状态的时间长度。 //默认为110秒 GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(110); //该值表示在连接停止之后引发断开连接事件之前要等待的时间长度。 //默认为30秒 GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(30); //用于表示两次发送保持活动消息之间的时间。如果启用,此值必须至少为两秒。设置为 null 可禁用。 //默认为10秒,设置DisconnectTimeout后默认为DisconnectTimeout的3分之一 GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(10);
注意一点,这些配置是写在你的Global.asax的Application_Start()方法中的,切勿写在Owin启动器中..
二、如何在服务器的其他类中使用Hub:
如下:
using System.Collections.Generic; using System.Linq; using System.Web; namespace SignalRTest { public class Class1 { //获取相关的集线器 Microsoft.AspNet.SignalR.IHubContext context = Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<SignalRTest.MoveTextHub>(); public void aaa(string message) { context.Clients.All.broadcastMessage(message + DateTime.Now.ToString()); } } }
三、使用自己的连接ID
老规矩,前言~,在此先道个歉,之前的1-5对很多细节问题都讲的不是很详细,也有很多人在QQ或者博客问我一些问题
所以,特开了这个续集.. - -, 讲一些大家在开发中遇到的问题和一些解决方案,今天就来说说经常被问到的,如何使用自己定义的连接ID.
之前我们说过,Signalr提供了唯一的连接ID 获取方法:Context.ConnectionId,
那么怎么自己定义这个东西呢? (废话一堆 - - ,),进入主题:
首先,其实在Signalr的前期版本是可以直接自定义Context.ConnectionId,
使用老版本的可以自行查看IConnectionIdGenerator,
IConnectionIdFactory 这两个接口.
所以特意说明一下,本博客这里的代码,只适用于Signalr2.0以上版本
其实在2.0的版本中,SignalR团队为了安全性,已经完全去除了自定义Context.ConnectionId的接口,但是相应的开放了相对安全的IUserIdProvider
废话不多说,直接上代码:
首先帐户登陆的代码:
其实就是很传统的登陆代码..把一些用户信息写入到Cookie中而已.黄色为重点
public class UserController : ApiController { [HttpGet] public object Login(string name,string pwd) { UserInfoBLL bll = new UserInfoBLL(); if (CacheHelper.Get(name) == null) { var userinfo = bll.LoginUser(name, pwd); if (userinfo != null) { var context = HttpContext.Current; //帐户信息写入Cookie,自行加密 context.Response.Cookies.Add(new HttpCookie(UserEnum.INFO) { Value = JsonConvert.SerializeObject(userinfo) }); //唯一的登陆ID,作为连接ID context.Response.Cookies.Add(new HttpCookie(UserEnum.SignalRID) { Value = userinfo.LoginName }); return new { State=true,Message="登陆成功!"}; } else { return new { State=false,Message="帐户或密码输入错误!"}; } } else { return new { State=false,Message="该帐户已经登陆!"}; } } }
接下来实现IUserIdProvider:
public class MyUserFactory : IUserIdProvider { public string GetUserId(IRequest request) { if (request.GetHttpContext().Request.Cookies[UserEnum.SignalRID] != null) { return request.GetHttpContext().Request.Cookies[UserEnum.SignalRID].Value; } return ""; // return Guid.NewGuid().ToString(); } }
以上代码是创建一个MyUserFactory类,继承自IUserIdProvider,实现IUserIdProvider的抽象方法GetUserId
这里的ID我们从Cookies中获取,细心的人应该已经发现了,有个IRequest的参数,所以原则上你可以使用IRequest的各种属性比如QS..你随意..(注:Session暂时无法使用,原因未知)
接下来,重点来了..
在Starup中,把我们自定义的MyUserFactory注入到回话设置中..
代码如下(黄色为重点):
public class Startup { public void Configuration(IAppBuilder app) { // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888 //重点,将MyUserFactory注入 var userIdProvider = new MyUserFactory(); GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => userIdProvider); //设置Webapi var config = new HttpConfiguration(); config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); app.UseWebApi(config); app.MapSignalR(); } }
接下来在Hub中添加代码如下:
/// <summary> /// 获取连接ID,你可以写成自己的扩展方法,或设置成属性,自行定义 /// </summary> /// <returns></returns> public string GetSignalrID() { if (Context.Request.GetHttpContext().Request.Cookies[UserEnum.SignalRID] != null) { return Context.Request.GetHttpContext().Request.Cookies[UserEnum.SignalRID].Value; } return ""; } //编写发送信息的方法 public void SendMessage(string message) { string id = Context.ConnectionId; string username = Context.User.Identity.Name; var userinfo = JsonConvert.DeserializeObject<UserInfo>(Context.Request.GetHttpContext().Request.Cookies[UserEnum.INFO].Value); var Message = new { name = userinfo.UserName, loadname = userinfo.LoginName, picurl = userinfo.UserPicUrl, time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), message = message }; Clients.User(GetSignalrID()).broadcastMessage(Message); }
说明:重点是标黄色的地方,看过我之前文章的都知道,之前我们的对指定连接对象发送数据,写法为: Clients.Client("连接ID").客户端方法,
这里我们换成了Clients.User("自定义ID"),这样就完成了整个使用自己的连接ID的替换工作.
参考资料:
http://www.cnblogs.com/GuZhenYin/p/4744786.html
SignalR2.0开发实例之——设置时间、后台其他地方使用集线器、使用自己的连接ID的更多相关文章
- SignalR2.0开发实例之——私聊
一.前言 继续上一章的补充,这章介绍使用私聊的功能.主要通过一个方法 Clients.Client(Context.ConnectionId).showMessage(msg); SignalR框 ...
- SignalR2.0开发实例之——群发消息
一.前言 ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相 ...
- SignalR2.0开发实例之——创建房间聊天
SignalR作为一个强大的集线器,已经在hub里面集成了Gorups,也就是分组管理,使用方法如下: //作用:将连接ID加入某个组 //Context.ConnectionId 连接ID,每个页面 ...
- SignalR2.0开发实例之——负载均衡
SignalR 2.0作为一个新的而且强大的通信工具,发布博客之后得到了很多人的支持,谢谢...也有人对性能和架设等问题提出了各种质疑..真的很感谢.. 我特意下载了SignalR 2.0的源码硬着头 ...
- 一篇对OAuth2.0开发实例的介绍
今天看到了博友对SSO的文章,SSO单点登录的讲解突然想写一篇关于OAuth2.0用户授权的介绍. 应用场景:在APP或者网页接入一些第三方应用时,时长会需要用户登录另一个合作平台,比如QQ,微博,微 ...
- 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(中)
接<基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(上)> 三.代码分析 1.界面初始化 bool PlaneWarGame::init() { bool bRet = fals ...
- Vuejs实例-00Vuejs2.0全家桶结合ELementUI制作后台管理系统
Vuejs2.0全家桶结合ELementUI制作后台管理系统 0: 系统环境的介绍 1: Vuejs实例-01使用vue-cli脚手架搭建Vue.js项目 2: Vuejs实例-02Vue.js项目集 ...
- 【eclipse插件开发实战】 Eclipse插件开发5——时间插件Timer开发实例详解
Eclipse插件开发5--时间插件Timer开发实例详解 这里做的TimeHelper插件设定为在菜单栏.工具栏提供快捷方式,需要在相应地方设置扩展点,最后弹出窗体显示时间. 在上一篇文章里创建好了 ...
- 【Android 开发实例】时间管理APP开发之数据库设计
当然也能够先写界面什么的.可是,总认为先把数据库后台写好在写界面比較放心. 对于数据库的设计,我一開始没什么概念.甚至不知道怎样下手,一開始想着设计成几个表?有哪些字段? 最后用了两天时间,还是一无所 ...
随机推荐
- iBox v2.0 发布,Web化仿iOS7界面/交互的JavaScirpt库
iBox2 是一个仿 iOS 7 界面/交互的 JavaScirpt 库,它运行在 webkit 内核的移动浏览器之上,依赖 iScroll5,帮助开发者构建更接近 iOS 体验的 WebApp. 伴 ...
- 一些 CSS 框架
利用 CSS 框架,可以简化你的工作,提高工作效率.CSS 框架是一系列 CSS 文件的集合体,包含了基本的元素重置,页面排版.网格布局.表单样式.通用规则等代码块.下面给你推荐了27款优秀的CSS框 ...
- js解决网页无法复制文字的问题
碰到有些网站,站长禁止了右键,或者用其它方法不让复制网页的文字,弄的好烦人啊,虽然这是小把戏,但多多少少造成了一些不方便,前几天发现这个解决不能复制问题的小方法,一行代码即搞定,就是下面这行: jav ...
- 一个PHP常用表单验证类(基于正则)
一个基于正则表达式的PHP常用表单验证类,作者:欣然随风.这个表单判断类的功能有:验证是否为指定长度的字母/数字组合.验证是否为指定长度汉字.身 份证号码验证.是否是指定长度的数字.验证邮件地址.电话 ...
- Unity3D 经验记录
1.using UnityEngine.SceneManagement; 当在01场景调用02场景时,再载入回01场景时,代码保存的变量不会初始化,预制物体脚本内的变量会初始化. 2.当子物体太多时, ...
- Android onActivityResult 设置requestCode 返回的code不对
今天在项目里用到 Intent intent=new Intent(getActivity(), Test.class);startActivityForResult(intent, 1); onAc ...
- jQueryMobile之Popup
效果: (1):Tooltip (2):Menu (3):NestedMenu (4):Login ------ 源码: <!DOCTYPE html> <html lang=&qu ...
- 2个Web上传组件
http://www.uploadify.com/download/ http://gmupload.tanjun.com.cn/
- 关于标准C语言的预定义宏
标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义.下面预定义宏表,被我抄了下来.__LINE__ 当前 ...
- sdl2.0示例
// gcc -o testDrone2_video testDrone2_video.c -lavcodec -lavformat -lswscale -lSDL2// g++ -o testDro ...