ASP.NET SignalR 與 LayIM2.0 配合輕松實現Web聊天室(二) 之 ChatServer搭建,連接服務器,以及注意事項。


  上篇:ASP.NET SignalR 與 LayIM2.0 配合輕松實現Web聊天室(一) 之 基層數據搭建,讓數據活起來(數據獲取)

  上一篇我們已經完成了初步界面的搭建工作,本篇將介紹IM的核心內容了,就是SignalR的Hub類。整個即時通訊機制都是以它為基礎的。至於原理我也不再講解,講了也不如專業的文章講得好。所以我們直接看業務,上代碼。有一部分原理 在文章 ASP.NET SignalR 與LayIM配合,輕松實現網站客服聊天室(二) 實現聊天室連接 (當時是LayIM1.0版本)。原理是一樣的,不過這次我把Server端單獨提取出來,為了防止 Server端和UI端過度耦合,拆分不方便。進入正題:

  打開項目 LayIM.ChatServer,新建LayIMHub類繼承自Hub。(這里要添加Microsoft.AspNet.SignalR.Core,Microsoft.AspNet.SignalR.SystemWeb的引用)核心方法如下:

  上邊三個重寫的方法一看就很明白,通過這幾個方法,客戶端很容易知道自己的連接狀態。我們主要看下邊四個方法。

  • 單聊連接(ClientToClient):這個方法就是當用戶點擊某個人的頭像打開聊天界面的時候,要調用的方法,目的是讓當前聊天的兩個人分配到一個組里。(當然:Clients.Client(connectionId)才是真正的給某個Client發送消息的方法),我這里用的原理就是群組,就算是兩個人聊天,相當於一個群里面只有兩個人,所以,兩個人和多個人聊天原理是相同的。文字有些抽象,畫個圖大家應該就明白了

  

  上圖就是用戶A想和用戶B聊天打開聊天窗口時的流程,同理如果B恰好也打開了A的窗口,那么組 FRIEND_10001_10000 里面就是存在A和B兩個客戶端,那么他們倆發的消息就是他們兩個人能夠收到了。之所以把自己發送的消息還返回給自己,那是因為,這樣客戶端能夠知道我的消息是否發送成功,因為layim在客戶端發送消息時已經做了處理,直接將消息加入到聊天框的,但是服務端可能沒有收到。所以可能會出現客戶端瘋狂發消息,但是服務端(對方)一條也沒有接收到的情況。還有另外一種情況,A,B都在線,但是B沒有打開A的聊天窗口怎么辦呢?這里先賣個關子,涉及到后邊的在線人員統計機制了。用這個可以做好多東西,只要是客戶端涉及是否在線的都可以用到。

  然后我們在UI端引用ChatServer.dll ,新建Startup(如果沒有的話),代碼如下:

  

using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartupAttribute(typeof(LayIM_SignalR_Chat.V1._0.Startup))]
namespace LayIM_SignalR_Chat.V1._0
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            //ConfigureAuth(app);
            app.Map("/layim", map =>
            {
                var hubConfiguration = new HubConfiguration()
                {
                    EnableJSONP = true
                };
                map.RunSignalR(hubConfiguration);
            });
        }
    }
}

  頁面上需要引用 jquery.js,signalr.js,/layim/hubs (這個是客戶端代理自動生成的),另外,我自己寫了個簡單的服務調用封裝 hub.js,先運行項目,看看自動生成的代碼有沒有:(http://localhost:8496/layim/hubs)

 

/*!
 * ASP.NET SignalR JavaScript Library v2.1.2
 * http://signalr.net/
 *
 * Copyright Microsoft Open Technologies, Inc. All rights reserved.
 * Licensed under the Apache 2.0
 * https://github.com/SignalR/SignalR/blob/master/LICENSE.md
 *
 */

/// <reference path="..\..\SignalR.Client.JS\Scripts\jquery-1.6.4.js" />
/// <reference path="jquery.signalR.js" />
(function ($, window, undefined) {
    /// <param name="$" type="jQuery" />
    "use strict";

    if (typeof ($.signalR) !== "function") {
        throw new Error("SignalR: SignalR is not loaded. Please ensure jquery.signalR-x.js is referenced before ~/signalr/js.");
    }

    var signalR = $.signalR;

    function makeProxyCallback(hub, callback) {
        return function () {
            // Call the client hub method
            callback.apply(hub, $.makeArray(arguments));
        };
    }

    function registerHubProxies(instance, shouldSubscribe) {
        var key, hub, memberKey, memberValue, subscriptionMethod;

        for (key in instance) {
            if (instance.hasOwnProperty(key)) {
                hub = instance[key];

                if (!(hub.hubName)) {
                    // Not a client hub
                    continue;
                }

                if (shouldSubscribe) {
                    // We want to subscribe to the hub events
                    subscriptionMethod = hub.on;
                } else {
                    // We want to unsubscribe from the hub events
                    subscriptionMethod = hub.off;
                }

                // Loop through all members on the hub and find client hub functions to subscribe/unsubscribe
                for (memberKey in hub.client) {
                    if (hub.client.hasOwnProperty(memberKey)) {
                        memberValue = hub.client[memberKey];

                        if (!$.isFunction(memberValue)) {
                            // Not a client hub function
                            continue;
                        }

                        subscriptionMethod.call(hub, memberKey, makeProxyCallback(hub, memberValue));
                    }
                }
            }
        }
    }

    $.hubConnection.prototype.createHubProxies = function () {
        var proxies = {};
        this.starting(function () {
            // Register the hub proxies as subscribed
            // (instance, shouldSubscribe)
            registerHubProxies(proxies, true);

            this._registerSubscribedHubs();
        }).disconnected(function () {
            // Unsubscribe all hub proxies when we "disconnect".  This is to ensure that we do not re-add functional call backs.
            // (instance, shouldSubscribe)
            registerHubProxies(proxies, false);
        });

        proxies['layimHub'] = this.createHubProxy('layimHub'); 
        proxies['layimHub'].client = { };
        proxies['layimHub'].server = {
            clientSendMsgToClient: function (message) {
                return proxies['layimHub'].invoke.apply(proxies['layimHub'], $.merge(["ClientSendMsgToClient"], $.makeArray(arguments)));
             },

            clientSendMsgToGroup: function (message) {
                return proxies['layimHub'].invoke.apply(proxies['layimHub'], $.merge(["ClientSendMsgToGroup"], $.makeArray(arguments)));
             },

            clientToClient: function (fromUserId, toUserId) {
                return proxies['layimHub'].invoke.apply(proxies['layimHub'], $.merge(["ClientToClient"], $.makeArray(arguments)));
             },

            clientToGroup: function (fromUserId, toGroupId) {
                return proxies['layimHub'].invoke.apply(proxies['layimHub'], $.merge(["ClientToGroup"], $.makeArray(arguments)));
             }
        };

        return proxies;
    };

    signalR.hub = $.hubConnection("/layim", { useDefaultPath: false });
    $.extend(signalR, signalR.hub.createHubProxies());

}(window.jQuery, window));
自動生成的hubs代碼

  可以看到,上述代碼server已經對應了服務端我們自定義的方法。(這里注意,當我們調用server端的方法的時候,首字母都是小寫的。)

  

  客戶端連接服務器核心代碼:

  

//連接服務器
                connect: function () {
                    $.connection.hub.url = _this.option.serverUrl;
                    _this.proxy.proxyCS = $.connection.layimHub;
                    $.connection.hub.start({ jsonp: true }).done(function () {
                        //連接服務器
                        //TODO處理聊天界面之前的邏輯
                        //console.log('自定義連接服務器成功方法:' + success);
                        if (call.ready) {
                            for (var i = 0; i < call.ready.length; i++) {
                                call.ready[i]({ connected: true });
                            }
                        }
                        console.log('連接服務器成功');
                    }).fail(function () {
                        //console.log('自定義連接服務器成功方法:' + success);
                        if (call.failed) {
                            for (var i = 0; i < call.failed.length; i++) {
                                call.failed[i]({ connected: false });
                            }
                        }
                    });
                },

  不知不覺竟然寫成了倒敘,給大家解釋一下,上文中A和B能夠連接的前提條件是 初始化連接服務器能夠成功,也就是說客戶端調用connect方法然后能夠打印 ‘連接服務器成功’。

  最后呢,跟Layim1.0不同的是Layim2.0引用js的方法有所變化,類似seajs的語法。所以,我們的hub代碼要改成如下形式:

  autohub.js

  

  signalr.2.1.2.min.js

  

  hub.js

  

  我們都以這種形式定義成模塊之后,需要在頁面中添加模塊:

  

 //自定義模塊
    layui.extend({
        signalr: '/scripts/signalr/signalr',
        autohub: '/scripts/signalr/autohub',//自動生成的
        hub: '/Scripts/signalr/hub',
           
    });

  最后,我們以use的形式開啟服務端:

  

  運行項目看一下,打印輸出:

  

  到此為止,連接服務器工作已經完成了,總結一下:

  1.創建Hub文件

  2.修改相應config(startup)

  3.修改相應的js代碼規范(layui.use)

  4.界面初始化之后調用connect方法。

 

  本篇就到這里了,由於項目還在進行中,暫時不能提供源代碼,不過思路應該沒問題吧,如果對博客中有什么疑問或者看法的話,歡迎在底下評論交流。

      下篇預告【初級】ASP.NET SignalR 與 LayIM2.0 配合輕松實現Web聊天室(三) 之 實現單聊,群聊,發送圖片,文件。

 

   想要學習的小伙伴,可以關注我的博客哦,我的QQ:645857874,Email:fanpan26@126.com

   GitHub:https://github.com/fanpan26/LayIM_NetClient/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM