一. 承上声明
几点介绍:
1. PersistentConnection(永久连接)相对于Hubs模式,更加偏向底层,它的编程模式与WebSocket的写法很类似,固定方法发送和接受,不能向Hub模式那样 客户端和服务端相互调用各自定义的方法。
2. 该模型主要用于:单个发件人、分组、广播消息的简单终结点。
二. 从零开始搭建
1. 新建MVC5项目,通过Nuget安装:Microsoft.AspNet.SignalR程序集,安装成功后如下图:
2. 新建一个永久连接模型类(MyPresitentConnection1),该类继承了PersistentConnection,并且override几个必要方法。
3. 新建一个OWIN Startup Class(Startup),并在Configuration方法中指定使用的通讯模型的URl, 如: app.MapSignalR<MyPresitentConnection1>("/myPreConnection1");
PS: 程序启动时候首先会找到该类,然后运行里面的Configuration方法,从而url和通讯模型的匹配将生效。
4. 在前端页面中书写SignalR的代码,与服务器端MyPresitentConnection1类进行连接,实现相应的通讯业务。
三. 核心方法介绍
1. 服务器端代码
(1). OWIN Startup Class即Startup中要配置url和通讯模型向匹配,这里的url在web前端页面的js中要使用,代码如下:
1 public class Startup 2 { 3 public void Configuration(IAppBuilder app) 4 { 5 // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888 6 //1. 基本用法的配置 7 app.MapSignalR<MyPresitentConnection1>("/myPreConnection1"); 8 } 9 }
(2). 永久连接模型类MyPresitentConnection1继承了PersistentConnection,并且可以override几个方法。
A. PersistentConnection中可以override的几个主要方法有:
①. OnConnected :连接成功后调用
②. OnReceived:接收到请求的时候调用
③. OnDisconnected:连接中断的时候调用
④. OnReconnected:连接超时重新连接的时候调用
B. 核心业务主要使用PersistentConnection类中的Connection属性,有两个核心方法
①. 1对1发送消息: public static Task Send(string connectionId, object value);
②. 1对多发送消息: public static Task Send(IList<string> connectionIds, object value);
③. 广播(群发,可以去掉不发送的人): public static Task Broadcast(object value, params string[] excludeConnectionIds);
PS:发现每个override里都有一个参数connectionId,它代表,每个客户端连接服务器成功后都会产生一个标记,这个标记是GUID产生的,它是唯一的, 不会重复, 在业务中可以通过该标记connectionId来区分客户端。
下面我的代码中书写的业务为:
①. OnConnected方法即连接成功后调用的方法,调用Send方法告诉自己登录成功(当然你也可以根据实际业务告诉指定的人)。
②. OnReceived方法即接受请求的方法,调用Send方法向指定人一对一发送消息。
③. OnDisconnected方法即连接中断的方法,调用Broadcast方法向所有人发送消息,某某已经退出。
④. OnReconnected方法即超时重新连接方法,执行重连业务。
分享代码:
2. 前端Html页面
(1). 引入JS库,这里包括JQuery库和SignalR库(JQuery最低版本为1.6.4)。
(2). 配置路径:$.connection("/myPreConnection1");需要与Startup中的对应
(3). 常用的几个方法有:
① start:开启连接
② received:接受服务器发送来的消息
③ disconnected:连接中断时调用
④ error:连接发生错误的时嗲用
④ stop:断开连接
⑤ send:发送消息
另外还有:connectionSlow、stateChanged、reconnecting、reconnected等等
(4). 当前连接状态有4种
connecting: 0(正在连接), connected: 1(正常连接,连接成功中), reconnecting: 2(正在重连), disconnected: 4 (掉线了)
PS: 以上代码和WebSocket确实很像,下图为WebSocket相关方法。
(5). 下面我的代码中的业务
分享代码:
(6). 运行效果
四. 分组的概念
1. PersistentConnection类中提供了一个 IConnectionGroupManager Groups的概念,即可以将不同用户分到不同组里,就好比QQ的中的讨论组, 在这个组里发信息,该组里的所有人都能看到,但别的组是看不到的。并提供了两个方法分别是
①. 加入组:Task Add(string connectionId, string groupName)
②. 移除组:Task Remove(string connectionId, string groupName)
IConnectionGroupManager下提供两个针对组进行发送消息的方法
①. 针对单个组(可以去掉不发送的人):Task Send(string groupName, object value, params string[] excludeConnectionIds);
②. 针对多个组(可以去掉不发送的人):Task Send(IList<string> groupNames, object value, params string[] excludeConnectionIds);
注:一个客户端可以同时加入多个组的,就好比qq,一个用户你可以同时在多个讨论组里讨论,相互不影响。
2. 需求背景:
有两个房间,分别是room1和room2,将2个人加入到room1里,2两个人加入到room2里,1个既加入room1且加入room2,测试向指定组发送消息和普通的群发消息。
测试页面如下图:
3. 先贴代码后分析
实体类代码
服务器端代码
Html代码
代码分析:
通过客户端发送过来的action字段来区分几种情况。
① 当为“enter”时,表示建立组关系,并提示自己进入房间成功,通知其他人欢迎信息。
② 当为“sendRoom”时,表示向指定组发送消息
③ 当为空时,表示普通的向所有人发送消息,不区分组的概念
4. 效果展示(实在是难截图啊)
5. 开始吐槽
本来框架默认提供一个组的概念,方便了我们对一些业务的开发,是一好事,但是竟然不能获取每个组内的connectionId列表,这。。。太坑了,不伦不类的,还得自己记录一下哪个组中有哪些connectionId,坑啊,微软baba真不知道你是怎么想的。
五. 跨域请求
1. SignalR跨域请求的默认是关闭的,我们可以自行开启,SignalR支持的跨域请求有两种:
①:JSONP的模式,仅支持Get请求,需要服务器端配合,传输数据大小有限制
②:Cors模式,支持Post、Get等请求,需要在浏览器中加 【Access-Control-Allow-Origin:*】类似的配置
2. 开启跨域请求的方式,详见下面代码:
1 public class Startup 2 { 3 public void Configuration(IAppBuilder app) 4 { 5 //1. JSONP的模式 6 //app.MapSignalR<MyPresitentConnection1>("/myPreConnection1", new Microsoft.AspNet.SignalR.ConnectionConfiguration() 7 //{ 8 // EnableJSONP = true 9 //}); 10 11 //2. Cors的模式(需要Nuget安装:Microsoft.Owin.Cors程序集) 12 //app.Map("/myPreConnection1", (map) => 13 //{ 14 // map.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 15 //}); 16 17 //3. JSONP和Cors同时开启 18 //app.Map("/myPreConnection1", (map) => 19 //{ 20 // //1. 开启 jsonp 21 // map.RunSignalR<MyPresitentConnection1>(new Microsoft.AspNet.SignalR.HubConfiguration() { EnableJSONP = true }); 22 // //2. 开启cors 23 // map.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 24 //}); 25 26 } 27 }
3. 跨域请求的作用是什么,在后面章节和Hubs模型一起介绍
六. 第三方调用
以上所有的代码与通信相关的代码都写在永久连接类中,但在开发中经常会遇到,我要在控制器中的某个方法中调用相应的方法,发给用户信息,这个时候怎么办呢?
可以通过:GlobalHost.ConnectionManager.GetConnectionContext<MyPresitentConnection1>();来获取永久连接类,然后调用相应的方法。
代码如下:
1 /// <summary> 2 /// 向所有人发送消息 3 /// </summary> 4 /// <param name="msg">发送的信息</param> 5 public string MySendAll(string msg) 6 { 7 string myConnectionId = Session["connectionId"].ToString(); 8 //PersistentConnection模式 9 var perConnection = GlobalHost.ConnectionManager.GetConnectionContext<MyPresitentConnection1>(); 10 perConnection.Connection.Broadcast(msg); 11 return "ok"; 12 }
关于具体结合业务的样例在下一节的Hub的例子详细编写,原理都一样。
郑州男科医院:http://www.zztongjiyiyuan.com/郑州男性医院哪家好:http://www.zztongjiyiyuan.com/郑州专业男科医院【挂号】:http://www.zztongjiyiyuan.com/郑州好的男科医院:http://www.zztongjiyiyuan.com/郑州哪家医院看男科好:http://www.zztongjiyiyuan.com/郑州专业男科医院:http://www.zztongjiyiyuan.com/郑州男科医院哪里好:http://www.zztongjiyiyuan.com/https://yyk.familydoctor.com.cn/12248/