<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    一、SignalR 概述
    https://docs.microsoft.com/en-us/aspnet/signalr/index
    SignalR是微軟為實現實時通信的一個類庫。一般情況下,signalR會使用JavaScript的長輪詢(long polling)的方式來實現客戶端和服務器通信,隨著Html5中WebSockets出現,SignalR也支持WebSockets通信。另外SignalR開發的程序不僅僅限制于宿主在IIS中,也可以宿主在任何應用程序,包括控制臺,客戶端程序和Windows服務等,另外還支持Mono,這意味著它可以實現跨平臺部署在Linux環境下。

        signalR內部有兩類對象:
    1. 持久連接
      一個持久連接代表了一個端點,它可以發送單一接收者,Group接受者或者廣播信息。持久連接的api是SignalR提供給開發者進入低級別協議的api。連接模型使用起來和WCF比較類似。
    2. Hubs(集線器)
      Hubs是SignalR提供的高級別的api,它允許客戶端和服務端,在自己這邊相互調用對方的方法。Hubs模型類似于.Net Remoting。使用Hubs也可以讓你傳遞強類型參數,進行模型綁定。
    SignalR將整個信息的交換封裝起來,客戶端和服務器都是使用JSON來溝通的,在服務端聲明的所有Hub信息,都會生成JavaScript輸出到客戶端,.NET則依賴Proxy來生成代理對象,而Proxy的內部則是將JSON轉換成對象。



    SignalR 和 WebSocket
    如果客戶端和服務器都支持WebSocket,那么SignalR會通過WebSocket來傳輸數據。當然你也可以自己使用WebSocket來實現SignalR的功能,不過使用SignalR你就不用考慮如果客戶端或者服務器不支持WebSocket的問題了。

    二、SignalR的協議選擇
    SignalR是可以在客戶端和服務器端進行即時通訊的幾種協議的抽象和實現。一個SignalR連接是通過http請求發起的,然后上升為WebSocket(如果客戶端和服務端都支持)。WebSocket是SignalR最理想的協議,它可以有效地利用服務器端的內存,有著最低的延遲,最多的基礎特性(比如客戶端和服務端的全雙工連接),不過它也有著嚴格的要求,需要服務器端使用Windows Server 2012或者Windows 8以上的系統,也需要.NET Framework 4.5.。如果不符合這些要求,那么SignalR會使用其他的協議來建立連接。

    HTML 5協議
    ?WebSocket。如果服務器和客戶端都支持,那么就使用WebSocket協議來進行通訊。
    ?服務器推送事件(Server-sent Events)。除了IE,其他的瀏覽器基本都支持。
    Comet協議
    ?Forever Frame (只支持IE)。
    ?Ajax長輪詢(Ajax long polling)。
    SignalR協議選擇過程
    1.如果瀏覽器是IE8或者更早的版本,使用長輪詢。
    2.如果配置了Jsonp(如果連接開始的時候jsonp的參數設置為true), 使用長輪詢。
    3.如果是跨域連接, 如果下面的條件符合就會使用WebSocket,如果有條件不符合,那就是用長輪詢。
        ?客戶端支持跨域連接
        ?客戶端支持WebSocket
        ?服務器端支持WebSocket
    4.如果沒有配置jsonp,而且不是跨域連接,如果客戶端和服務端都支持WebSocket,那么就使用WebSocket。
    5.如果客戶端或者服務端不支持WebSocket,使用服務器推送事件。
    6.如果不支持服務器推送事件,使用Forever Frame。
    7.如果不支持Forever Frame,使用長輪詢。

    監控協議
    可以通過在你的Hub上開啟logging來監控你的SignalR使用了什么協議。
    $.connection.hub.logging = true;

    指定協議
    SignalR判斷協議也需要消耗一定的客戶端、服務端資源,如果你清楚客戶端、服務端支持的協議,那么你可以指定使用某種協議來建立連接。
    比如,你知道客戶端只支持長輪詢,那么你可以指定使用長輪詢來進行通訊。
    connection.start({ transport: 'longPolling' });

    你也可以指定一個序列,客戶端會按照序列里的順序來進行通訊。下面的代碼的作用是,先使用WebSocket,如果失敗了,就使用長輪詢。
    connection.start({ transport: ['webSockets','longPolling'] });

    SignalR包含下面四種指定的協議常量
        ?webSockets
        ?foreverFrame
        ?serverSentEvents
        ?longPolling
    三、SignalR的三種實現方式
    1. 集線器類(Hub) + 非自動生成代理模式
    服務端與客戶端分別定義的相對應的方法,客戶端通過代理對象調用服務端的方法,服務端通過IHubConnectionContext回調客戶端的方法,客戶端通過回調方法接收結果。
    JS端調用服務端方法采用:chat.invoke,而被服務端回調的方法則采用:chat.on (這里的chat是createHubProxy創建得來的)
                var conn = $.hubConnection();
                conn.qs = { "clientName": clientName };
                conn.start().done(function () {
                    $("#btnSend").click(function () {
                        var toUserId = eUsers.val();
                        if (toUserId != "") {
                            chat.invoke("sendOne", toUserId, $("#message").val())
                            .done(function () {
                                //alert("發送成功!");
                                $("#message").val("").focus();
                            })
                            .fail(function (e) {
                                alert(e);
                                $("#message").focus();
                            });
                        }
                        else {
                            chat.invoke("send", $("#message").val())
                            .done(function () {
                                //alert("發送成功!");
                                $("#message").val("").focus();
                            })
                            .fail(function (e) {
                                alert(e);
                                $("#message").focus();
                            });
                        }
                    });
                });
     
                var chat = conn.createHubProxy("chat");
                chat.on("receiveMessage", function (dt, cn, msg) {
                    var clsName = "linfo";
                    if (cn == clientName || cn.indexOf("您對") >= 0) clsName = "rinfo";
                    eChatBox.append("<p class='" + clsName + "'>" + dt + " <strong>" + cn + "</strong> 說:<br/>" + msg + "</p>");
                    eChatBox.scrollTop(eChatBox[0].scrollHeight);
                });
     
                chat.on("userChange", function (dt, msg, users) {
                    eChatBox.append("<p>" + dt + " " + msg + "</p>");
                    eUsers.find("option[value!='']").remove();
                    for (var i = 0; i < users.length; i++) {
                        if (users[i].Value == clientName) continue;
                        eUsers.append("<option value='" + users[i].Key + "'>" + users[i].Value + "</option>")
                    }
                });

    2. 集線器類(Hub)+ 自動生成代理模式
    需要js引用
    <script src="~/signalr/hubs" type="text/javascript"></script>
    然而,我們在寫代碼的時候上面的引用并不存在,而當運行后就會自動生成上述signalr的代理腳本
    這就是與非自動生成代理腳本最根本的區別,也正是因為這個自動生成的腳本,我們可以在JS中更加方便的調用服務端方法及定義回調方法,調用服務端方法采用:chat.server.XXX,而被服務端回調的客戶端方法則采用:chat.client.XXX

    3.持久化連接類(PersistentConnection)
    ?Startup.Configuration中是需要指定app.MapSignalR<MyConnection>("/MyConnection")
    ?需實現繼承自PersistentConnection類的自定義的持久化連接類,在這個連接中可以重寫:OnConnected、OnDisconnected、OnReceived、OnReconnected、ProcessRequest方法,同時有幾個重要的屬性成員Connection、Groups,服務端發消息給客戶端采用:Connection.Broadcast(廣播,所有客戶端都可以收到消息),Connection.Send(發送給指定的客戶端)

    具體實現參考
    https://www.cnblogs.com/zuowj/p/5674615.html

    四、使用RignalR實現新消息推送(集線器類(Hub)+ 自動生成代理模式
    1.app.MapSignalR();
    using System.Data.Entity;
    using Microsoft.Owin;
    using Owin;
    using RCRS.WebApp.Town.Migrations;
    using RCRS.WebApp.Town.Models.DomainEntity;

    [assembly: OwinStartupAttribute(typeof(RCRS.WebApp.Town.Startup))]
    namespace RCRS.WebApp.Town
    {
        public partial class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                ConfigureAuth(app);
                app.MapSignalR();

                Database.SetInitializer(new MigrateDatabaseToLatestVersion<TownContext, TownConfiguration>());
            }
        }
    }

    2. NotificationHub
    using System.Linq;
    using Microsoft.AspNet.SignalR;
    using Microsoft.AspNet.SignalR.Hubs;
    using RCRS.WebApp.Town.Models.Town;

    namespace RCRS.WebApp.Town.Hubs
    {
        [HubName("NotificationHub")] 
        public class NotificationHub : Hub
        {
            public void Connect(string userId)
            {
                var id = Context.ConnectionId;

                if (BizHub.ConnectedUsers.Count(x => x.ConnectionId == id) == 0)
                {
                    BizHub.ConnectedUsers.Add(new HubUser { ConnectionId = id, UserId = userId });
                    // send to caller
                    Clients.Caller.onConnected(id, userId, BizHub.ConnectedUsers);

                    // send to all except caller client
                    Clients.AllExcept(id).onNewUserConnected(id, userId);
                }
            }

            public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
            {
                var item = BizHub.ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
                if (item != null)
                {
                    BizHub.ConnectedUsers.Remove(item);

                    var id = Context.ConnectionId;
                    Clients.All.onUserDisconnected(id, item.UserId);

                }
                return base.OnDisconnected(stopCalled);
            }

        }
    }

    3.BizHub
            /// <summary>  </summary>
            public static List<HubUser> ConnectedUsers = new List<HubUser>();

            public void NotifyAll(string msg)
            {
                var hub = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
                hub.Clients.All.broadcaastNotif(msg);
            }

            public void NotifyPrivate(string toUserId, string msg)
            {
                var toUser = ConnectedUsers.FirstOrDefault(x => x.UserId == toUserId);
                var hub    = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();

                if (toUser != null)
                {
                    // send to 
                    hub.Clients.Client(toUser.ConnectionId).broadcaastNotif(msg);
                }
            }

            public void NotifyRole(List<string> roleLs, string msg)
            {
                List<string> lsUserIds = new List<string>();

                using (ApplicationDbContext context = new ApplicationDbContext())
                {
                    string cmd = getUsersByRoleLs(roleLs);
                    lsUserIds = context.Database.SqlQuery<string>(cmd).ToListAsync().Result;
                }

                foreach (string toUserId in lsUserIds)
                    NotifyPrivate(toUserId, msg);
            }

    4.引用js
    bundles.Add(new ScriptBundle("~/bundles/signalR").Include(
                    "~/Scripts/jquery.signalR-2.2.3.js"));

    5.
    <script src="~/signalr/hubs"></script>
        <script type="text/javascript">
            $(function () {
                var id = '@ViewBag.UserId';
                var notifyHub = $.connection.NotificationHub;
                notifyHub.client.broadcaastNotif = function (message) {
                    $("#assist-top-new-msg").text(message);
                    $("#assist-msg-list-new-flg").text(message);
                };

                $.connection.hub.start()
                    .done(function () {
                        console.log("Notification Hub Connected!");
                        //Server Call
                        notifyHub.server.connect(id);
                    })
                    .fail(function () {
                        console.log("Could not Connect Notification Hub!");
                    });

            });
        </script>



    posted on 2018-05-23 15:02 Ying-er 閱讀(1390) 評論(0)  編輯  收藏 所屬分類: .Net 、
    主站蜘蛛池模板: 国产亚洲成AV人片在线观黄桃 | 亚洲AV无码国产精品麻豆天美| 午夜亚洲乱码伦小说区69堂| 日韩电影免费在线| 亚洲另类无码专区丝袜| 在线成人a毛片免费播放| 天天爽亚洲中文字幕| 妞干网在线免费观看| 亚洲狠狠婷婷综合久久| 国产免费牲交视频| 有色视频在线观看免费高清在线直播 | 亚洲欧洲日韩综合| 免费成人福利视频| 国产亚洲sss在线播放| 夜夜爽免费888视频| 激情婷婷成人亚洲综合| 亚洲无码精品浪潮| 亚洲免费观看视频| 亚洲依依成人精品| 日本一区免费电影| 波霸在线精品视频免费观看| 亚洲av无码国产精品夜色午夜| 2019中文字幕在线电影免费| 色噜噜亚洲男人的天堂| 免费看一级做a爰片久久| 巨胸喷奶水视频www免费视频| 久久精品国产亚洲AV麻豆~| 999国内精品永久免费观看| 亚洲经典千人经典日产| 亚洲熟妇无码乱子AV电影| 亚洲视频免费在线看| 亚洲AV成人片无码网站| 亚洲区小说区图片区QVOD| 国产免费丝袜调教视频| 麻豆69堂免费视频| 亚洲AV无码AV男人的天堂| 在线观看人成网站深夜免费| 好湿好大好紧好爽免费视频| 亚洲av午夜精品无码专区| 久久精品国产亚洲AV不卡| 0588影视手机免费看片|