LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(四)之ASP.NET SignalR核心功能介绍

前言

本系列文章特点:使用ASP.NET SignalR和LayIM快速入门对接,实现一对一聊天,群聊,添加聊天群组,查找聊天记录等功能。源代码不包含LayIM的源代码,因为官方并没开源属于收费资源,所以得遵从官方的规则,但包含Demo的数据库脚本和改造之后的find.html,源代码在最后一节。

文章目录:

LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(一)之效果展示与关键技术简介

LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(二)之后台数据库创建

LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(三)之LayIM初始化数据

LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(四)之ASP.NET SignalR核心功能介绍

LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(五)之使用RabbitMQ缓存消息

LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(六)之SignalR与MVC结合封装消息发送与接收

LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(七)之LayIM与MVC数据交互实现单聊和群聊

LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(八)之改造查找页面实现拉取好友创建群

一、本文目标与简介

本文主要的目标针对ASP.NET SignalR对实现聊天消息的发送用到的一些核心功能点的介绍,为后面实现聊天消息发送接收做准备。

二、ASP.NET SignalR概述

ASP.NET SignalR在微软官方有详细的介绍并且提供了使用示例。大神(奔跑在路上)的系列文章《实时通讯系列目录篇之SignalR详解》也讲解的很详细,本文即主要借鉴该系列文章。我对SignalR研究也没有那么深入,在此就不献丑了,仅仅展示如何和LayIM对接。

三、Microsoft.AspNet.SignalR安装

1.安装SignalR

前面文章中创建LIM.Web项目,在此项目中通过Nuget安装Microsoft.AspNet.SignalR,安装后会在Scripts文件下增加两个js,如下图:

2.安装集线器

在LIM.Web中添加集线器,可以自定义重命名,本文命名为“ChatHub”,截图如下:

创建成功后,可以看到LayIM.Web项目下多了一个ChatHub.cs文件,ChatHub继承与Hub,它有OnConnected、OnDisconnected、OnReconnected这几个方法可以重写,可根据实际需要可以实现上线、离线通知,本文没有做特殊的业务处理,在微软官网或者其他大神的文章里,介绍这个文件如何使用很多。本文不再介绍,本文介绍的是这个文件如何和MVC结合。

3.创建Startup

OWINStartup类,官网有详细介绍,这里不再赘述,其实我对它研究并不深,也讲不出所以然,只能按照官网介绍明白它是干什么,有什么用以及怎么用,这里在LIM.Web项目中添加OWIN Startup Class类后,会在项目中增加一个Startup.cs文件,应用启动会首先运行该类,本文在Configuration方法中采用默认的方式 app.MapSignalR();截图与代码如下:

代码如下:

namespace LIM.Web
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }
}

4.添加js应用

添加的js有两个,一个是安装SignalR时生成的jquery.signalR-2.4.1.js,一个是应用运行时自动生成的代理类~/signalr/hubs,网上有很多关于第二个自动生成的代理的类的探讨以及自定义路由配置,本文不再探讨,使用默认模式。

至于安装SignalR时生成的jquery.signalR-2.4.1.js的引用,本demo放在BundleConfig文件中,所以加上之前LayIM的js的引用,完整的代码如下:

            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery.js", 
                        "~/Scripts/jquery.signalR-{version}.js",
                        "~/Scripts/layui/layui.js"
                        ));

至于第二个运行时生成的代理类,放在home的index页面中,<script src="~/signalr/hubs"></script>,可见源代码。或者在上篇文章LayIM初始化中截图也可以见到这句代码。

四、HubCallerContext.ConnectionId以及Clients和Groups简介

这三个东西是我们实现发送消息实现单聊和群聊的核心,具体实现微软已经封装好了,我们只需要使用即可。

1.ConnectionId

这个id是一个唯一的Guid,是代表每个用户身份的唯一id,用户登录成功会自动生成,SignalR发送与接收消息也是通过该Id来识别身份,所以这个Id的重要性不言而喻,前文中ChatHub类中可以直接通过 Context.ConnectionId来获取这个Id。注意的是,每次页面刷新这个Id都会重新生成,所以在实际项目中需要处理好这个Id和用户的对应关系。

2.Clients对象能实现的功能如下:

  1. All { get; }:向所有Id发送(包括自己)
  2. AllExcept(params string[] excludeConnectionIds):向所有Id发送(排除一些Id)
  3. Client(string connectionId):向指定Id发送,一对一
  4. Clients(IList<string> connectionIds):向一些Id发送,一对多
  5. Group(string groupName, params string[] excludeConnectionIds):向某个组发送(排除一些Id)
  6. Groups(IList<string> groupNames, params string[] excludeConnectionIds): 向多个组发送(排除一些Id)
  7. Users(IList<string> userIds):由Id标识的特定用户
  8. User(string userId):由Id标识的特定多用户

Clients已经提供了这么多方法,绝大多数的场景都可以满足了。本Demo中就只使用了Client和Group方法就实现了单聊和群聊的功能。

3.Groups对象

Clients.Group是可以给Group内的所有Id发送消息,所以某个Id想要接受到消息,前提就是需要添加到该Group。这个给我们群组聊天对应,一个群组对应一个group,name群组里所有人的id都应该在这个group里,Groups有两个方法一个是Add(string connectionId, string groupName),一个是Remove(string connectionId, string groupName)。

五、ConnectionId与用户对应存储

Signal中通过实时生成的ConnectionId来识别用户身份进行消息发送与接收,而我们应用中却无法存储该Id,因为它是实时生成的是动态的。我们用户表的主键是不变的。所以就需要建立一个映射关系,这里首先想到的就是C#里面的Dictionary,key用来对应我们用户表表的Id,Value用来存储ConnectionId。

上文中提到ConnectionId可以在ChatHub里面获取,但通常是我们应用运行时该Id还没生成或者在MVC里面不好获取这个Id,由此我们可以在前端获取到这个Id后主动将该Id推送到后台和用户表建立映射关系。本文前台代码如下:

                var conn = $.connection.hub;//SignalR
                //2. 与生成的代理类建立连接
                var proxy = $.connection.ChatHub;
                proxy.client.ReceiveOwnCid = function (connectionId) {
                    $.ajax({
                        url: "/LIM/AddConnectionId?connectionId=" + connectionId,
                        type: "get",
                        data: {},
                        dataType: "json",
                        success: function (data) {
                            if (!data.result) {
                                alert(data.message);
                            }
                        },
                        error: function (err) {
                            console.log(err);
                            alert("即时通讯连接错误:" + err.statusText)
                        }
                    });
                }

代码里 proxy.client.ReceiveOwnCid方法将ConnectionId发送给LIM/AddConnectionId来处理一些业务逻辑,关于这一块,我解决的思路是这样的,假如读到这里的朋友有在看了我的源代码后有其他解决方案麻烦告知我下,因为我总觉得有更好更合理的方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值