zoukankan      html  css  js  c++  java
  • 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.JSScriptsjquery-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/

  • 相关阅读:
    052-34
    052-33
    052-32
    052-31
    052-30
    052-28
    react组件之间通信
    排序算法
    点外卖
    js的各种排序算法
  • 原文地址:https://www.cnblogs.com/panzi/p/5748784.html
Copyright © 2011-2022 走看看