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/

  • 相关阅读:
    三次请求(读-改-读)引出nibernate 一级缓存
    算法竞赛入门经典第一、二章摘记
    uva 10905 Children's Game
    uva 11205 The broken pedometer
    uva 10160 Servicing stations
    uva 208 Firetruck
    uva 167 The Sultan's Successors
    zoj 1016 Parencodings
    uva 307 Sticks
    uva 216 Getting in Line
  • 原文地址:https://www.cnblogs.com/panzi/p/5748784.html
Copyright © 2011-2022 走看看