<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 、
    主站蜘蛛池模板: 亚洲产国偷V产偷V自拍色戒| 曰批视频免费30分钟成人| 一级毛片免费播放男男| 国产亚洲综合一区二区三区| 亚洲综合激情五月色一区| 亚洲人成片在线观看| 亚洲Av高清一区二区三区| 亚洲一区二区三区高清视频| 亚洲人成7777影视在线观看| 亚洲a级片在线观看| 亚洲第一成人在线| 亚洲另类自拍丝袜第五页| 亚洲AV无码一区二区三区性色| 亚洲国产无线乱码在线观看| 久久亚洲中文字幕无码| 国产成人va亚洲电影| 一级黄色免费毛片| 中文字幕乱码免费看电影| 日本免费人成网ww555在线| 日本免费一区二区久久人人澡| 1000部羞羞禁止免费观看视频| 免费无码肉片在线观看| 日韩激情淫片免费看| va亚洲va日韩不卡在线观看| 中文字幕精品亚洲无线码二区| 亚洲动漫精品无码av天堂| 亚洲福利秒拍一区二区| 亚洲中文字幕久久精品无码A| 久久无码av亚洲精品色午夜 | 免费在线黄色网址| 亚洲中文字幕无码永久在线| 久久久亚洲精品无码| 亚洲一级毛片免费看| 国产成人综合久久精品亚洲| 中文字幕成人免费高清在线| 8x8×在线永久免费视频| 德国女人一级毛片免费 | 久久精品国产这里是免费| 青草草色A免费观看在线| 国产yw855.c免费视频| 亚洲第一极品精品无码久久|