Fork me on GitHub

Asp.net SignalR

一、介绍

SignalR对websocket、SSE、长连接、forever frame进行封装。

websocket(html5):ws协议,这个协议基于tcp的。也就是说和http没有关系(兼容性不好)

SSE:客户端订阅服务器的一个事件,然后方便通过这个事件推送到客户端。  server => client 

长链接:保持一次链接的时间,例如保持一个链接5s

forever frame:在body中藏一个iframe,那么这个iframe和server是一个永久链接,如果server来数据,通过这个链接推送到client

 

二、PersistentConnection

1,参数

《1》 request: 获取一些链接中的附加信息,request.querystring
        request.cookie

        request是一个katana的包装类。

        singlaR 的request 其实是asp.net 中的 Request的子集。

《2》 connectionId 这个参数就是 客户端连接到服务器的唯一标识。。。也就说这个标识标识了客户端。本质上来说,和SessionID是一个性质。 【GUID】

2,demo

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(WebApplication1.Startup1))]

namespace WebApplication1
{
    public class Startup1
    {
        public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
            
            app.MapSignalR<MyConnection1>("/connection");
        }
    }
}
Startup1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;

namespace WebApplication1
{
    public class MyConnection1 : PersistentConnection
    {

        //js调用 start 触发
        protected override Task OnConnected(IRequest request, string connectionId)
        {
            return Connection.Send(connectionId, "Welcome!");
        }

        //js 调用send触发
        protected override Task OnReceived(IRequest request, string connectionId, string data)
        {
            return Connection.Broadcast(data);
        }

        //关闭连接(或者浏览器窗口)触发
        protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
        {
            return base.OnDisconnected(request, connectionId, stopCalled);
        }
    }
}
MyConnection1
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="Scripts/jquery-1.6.4.js"></script>
    <script src="Scripts/jquery.signalR-2.2.3.js"></script>
    <script type="text/javascript">
        var con = $.connection("/connection");

        //启动
        con.start(function (data) {
            con.send("asdasd")
        })

        con.received(function (data) {
            console.log("receive:"+data)
        })


    </script>
</head>
<body>

</body>
</html>
html

 

二、group(建简易聊天室)

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(WebApplication1.Startup1))]

namespace WebApplication1
{
    public class Startup1
    {
        public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
            
            app.MapSignalR<MyConnection1>("/connection");
        }
    }
}
Startup1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;

namespace WebApplication1
{
    public class MyConnection1 : PersistentConnection
    {
        private const string DEFAULT = "default";
        //js调用 start 触发
        protected override Task OnConnected(IRequest request, string connectionId)
        {
            this.Groups.Add(connectionId, DEFAULT);

            //excludeConnectionIds:排除通知的connectionId。在default组中,除了自己,其他人都能收到信息
            return this.Groups.Send(DEFAULT, connectionId + "进入房间", connectionId);
        }

        //js 调用send触发
        protected override Task OnReceived(IRequest request, string connectionId, string data)
        {
            //excludeConnectionIds:排除通知的connectionId。在default组中,除了自己,其他人都能收到信息
            return this.Groups.Send(DEFAULT, connectionId + ":" + data, connectionId);
        }

        //关闭连接(或者浏览器窗口)触发
        protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
        {
            return base.OnDisconnected(request, connectionId, stopCalled);
        }
    }
}
MyConnection1
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="Scripts/jquery-1.6.4.js"></script>
    <script src="Scripts/jquery.signalR-2.2.3.js"></script>
    <script type="text/javascript">
        $(function () {


            var con = $.connection("/connection");
            //启动
            con.start(function (data) {
            })

            con.received(function (data) {
                $("#context").append("<br/>"+data)
                console.log(data)
            })

            $("#send").click(function () {
                con.send($("#txt").val())
            })


        })

    </script>
</head>
<body>
    <input type="text" id="txt" />
    <input type="button" id="send" value="发送"/>
    <div id="context">

    </div>

</body>
</html>
html

案例下载:https://pan.baidu.com/s/1YJN-bwertKNQc2O5JHlQgg

 

三、Hub

1,js调用直接后端方法、后端直接调用js方法

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(WebApplication1.Startup1))]

namespace WebApplication1
{
    public class Startup1
    {
        public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
            app.MapSignalR();
        }
    }
}
Startup1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;

namespace WebApplication1
{
    public class MyHub : Hub
    {
        public void Hello()
        {
            //直接调用前端js方法
            Clients.All.aa("abc");
        }
    }
}
Hub
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="Scripts/jquery-1.6.4.js"></script>
    <script src="Scripts/jquery.signalR-2.2.3.js"></script>

    <!--引用js-->
    <script src="/signalr/js"></script>

    <script type="text/javascript">
        $(function () {

            //启动hub
            $.connection.hub.start()

            var conne = $.connection.myHub;

            //申明客户端js方法
            conne.client.aa = function (msg) {
                $("#context").append("<br/>" + msg)
            }

            $("#send").click(function () {
                //直接调用后端方法
                conne.server.hello();
            })


        })

    </script>
</head>
<body>
    <input type="text" id="txt" />
    <input type="button" id="send" value="发送"/>
    <div id="context">

    </div>

</body>
</html>
html

2,HubName/HubMethodName

using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;

namespace WebApplication1
{

    [HubName("MyHub")]
    public class MyHub : Hub
    {
        [HubMethodName("Hello")]
        public void Hello()
        {
            //直接调用前端js方法
            Clients.All.aa("abc");
        }
    }
}
MyHub

3,ConnectionId

 this.Context.ConnectionId;

 

四、Hub中的clients 和 groups属性

1,Clients

①T All { get; }

相当于持久连接中的 Broadcast。

②T AllExcept(params string[] excludeConnectionIds);

给排除本人所有人发送消息。(excludeConnectionIds排除的连接id)

③T Client(string connectionId);

跟Send操作就是一样的了。

④T Clients(IList<string> connectionIds);

和Send操作的重载方法一样,可以给一批指定的人发送。

⑤T Group(string groupName, params string[] excludeConnectionIds);

给房间中的指定人发送消息: Clients.Group("room1", "asdfasdfads");

⑥T Groups(IList<string> groupNames, params string[] excludeConnectionIds);

给房间列表中的指定人发送消息; 【天然的聊天室功能】

⑦T User(string userId);

这个和Client是有区别的。 这个userId => this.Context.Request.User.Identity.Name 【form验证】

cookie中间件来做到singlar的身份验证。

  userId 是你自己定义的一个标识。

T Users(IList<string> userIds);

2,Groups

①Task Add(string connectionId, string groupName);

向组内添加链接

②Task Remove(string connectionId, string groupName);

删除组内的连接

 

五、GlobalHost

1,获取Hub的上下文

var hub = GlobalHost.ConnectionManager.GetHubContext<MyHub>();

2,对singlar的全局设置

GlobalHost.Configuration.MaxIncomingWebSocketMessageSize:
websocket模式下,消息的传输大小,如果大于默认的64k,那么就会出问题。

GlobalHost.Configuration.DisconnectTimeout:
websocket强制关闭的时间。 30 seconds

GlobalHost.Configuration.TransportConnectTimeout:
传输的超时时间。 5s

 

六、生成代理js

下载安装nuget: Microsoft.AspNet.SignalR.Utils 

1,模板:signalr.exe ghp /path:《..\bin》 /o:《..\hub.js》
2,案例:
C:\Users\Hunter\Desktop\ConsoleApp3\packages\Microsoft.AspNet.SignalR.Utils.2.2.3\tools>signalr.exe ghp /path:C:\Users\Hunter\Desktop\ConsoleApp3\WebApplication2\bin /o:C:\Users\Hunter\Desktop\ConsoleApp3\WebApplication2\Scripts\hub.js
3,编译命令:
$(SolutionDir)packages\Microsoft.AspNet.SignalR.Utils.2.2.3\tools\signalr.exe ghp /path:$(SolutionDir)$(ProjectName)\$(OutDir) /o:$(SolutionDir)$(ProjectName)\Scripts\hub.js

4,替换代理js

 

七、支持跨域

①下载安装nuget: Microsoft.Owin.Cors 

②配置项

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;

[assembly: OwinStartup(typeof(WebApplication2.Startup))]

namespace WebApplication2
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
           
            app.UseCors(CorsOptions.AllowAll);
            app.MapSignalR();
          
        }
    }
}
Startup

③生成代理js

④修改代理js

⑤html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="Scripts/jquery-1.6.4.js"></script>
    <script src="Scripts/jquery.signalR-2.2.3.js"></script>

    <!--引用js-->
    <!--<script src="/signalr/js"></script>-->
    <script src="Scripts/hub.js"></script>
    <script type="text/javascript">
        $(function () {

            //启动hub
            $.connection.hub.start()

            var conne = $.connection.myHub;

            //申明客户端js方法
            conne.client.aa = function (msg) {
                $("#context").append("<br/>" + msg)
            }

            $("#send").click(function () {
                //直接调用后端方法
                conne.server.hello();
            })


        })

    </script>
</head>
<body>
    <input type="text" id="txt" />
    <input type="button" id="send" value="发送"/>
    <div id="context">

    </div>

</body>
</html>
html

案例下载:https://pan.baidu.com/s/1GY_Io63qZeECbGbEH589fg

 

八、集群部署

使用redis:

nuget: Microsoft.AspNet.SignalR.Redis 

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;

[assembly: OwinStartup(typeof(WebApplication2.Startup))]

namespace WebApplication2
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
            //使用redis做底板
            GlobalHost.DependencyResolver.UseRedis("localhost", 6379,string.Empty, "mykey");

            app.UseCors(CorsOptions.AllowAll);
            app.MapSignalR();
          
        }
    }
}
Startup

 

九、将singlar.exe 装入到 性能监视器

signlar.exe ipc 命令来安装性能监视器 [install performance counters]

signlar.exe upc 来卸载性能监视器 [uninstall performance counters]

 

十、HubPipeLine管道

实现:IHubPipelineModule

①入流: BuildIncoming 监控

②出流: BuildOutgoing 监控

 

posted on 2018-04-21 18:03  *Hunter  阅读(428)  评论(0编辑  收藏  举报

导航

AmazingCounters.com