SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)

SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升,5个Demo贯彻全篇,感兴趣的玩才是真的学)

官方demo:http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr

应用情景之一:

没太多连续的时间来研究SignalR,所以我把这篇文章分了三个阶段:

第一个阶段,简单使用,熟悉并认识SignalR

第二个阶段,实现上图的单聊效果

第三个阶段,实现类似QQ群发的功能

扩展阶段,如果有时间,逆天会再开一篇,封装一个LoTSignalR,看过逆天封装的人都知道,绝对简单又轻量级

比如LoTQQ,现在已经很多人在用了,后期会添加新功能,敬请期待~~

++++++++++++++++++ 我是华丽的分割线 +++++++++++++++++++++

步入正轨:

第一个阶段:

1.什么是ASP.NET SignalR?

ASP .NET SignalR是一个 ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信。什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消息及调用方法,当然这是实时操作的。

WebSockets是Html5提供的新的API,可以在Web网页与服务器端间建立Socket连接,当WebSockets可用时(即浏览器支持Html5)SignalR使用WebSockets,当不支持时SignalR将使用其它技术来保证达到相同效果。

SignalR当然也提供了非常简单易用的高阶API,使服务器端可以单个或批量调用客户端上的JavaScript函数,并且非常 方便地进行连接管理,例如客户端连接到服务器端,或断开连接,客户端分组,以及客户端授权,使用SignalR都非常 容易实现。

2.可以使用ASP.NET SingalR做什么?
SignalR 将与客户端进行实时通信带给了ASP .NET 。当然这样既好用,而且也有足够的扩展性。以前用户需要刷新页面或使用Ajax轮询才能实现的实时显示数据,现在只要使用SignalR,就可以简单实现了。

最重要的是您无需重新建立项目,使用现有ASP .NET项目即可无缝使用SignalR。

网上某架构图:

上面乱七八糟的估计很多人懒得看,好吧,你可以这样理解:

使用了SignalR就可以让客户端通过SignalR代理直接调用服务端的方法,让服务端通过SignalR直接调用客户端的方法

下面我们来实例演示一下,先演示一下不用IIS的情况:

新建一个控制台项目,引入 signalR Self Host (可以思考一下为什么会用NuGet包,他到底好在哪?O(∩_∩)O~不清楚等项目演示完你应该就知道了

这是他的依赖项

安装一下Owin.Cors

依赖项:

新增一个Owin的Startup类,类似于我们传统项目的Global文件

注册一下signalR中间组件(学过mvc的可以变相的理解为注册路由之类的)

在main方法中绑定端口(不一定是8080,比如我demo中就用的其他端口)

创建一个“SignalR集线器”(控制台这边因为没有集线器所以只能自己建类)

建了一个DntHub,定义了一个服务器端的方法,叫ServiceSend(一会会用到)

转到定义,看看Hub类(好东西啊,还有分组啥的,下面会讲)

运行一下,如果出错请参考我的这篇文章:Owin:“System.Reflection.TargetInvocationException”类型的未经处理的异常在 mscorlib.dll 中发生 - 毒逆天 - 博客园

先看看共引用多少dll(和MVC之类的比起是不是简洁很多?一会演示好处在哪)最小引用

创建一个web的Client,引用一下 SignalR的js包,其实你会发现就是多了几个js包并没有引用任何dll(必须的,不然岂不是太臃肿?)

前端的调用步骤:

    <!--
    总结一下:
    1.先引入jq包,再引入signalR的js包,再引入signalR动态生成的hubs
    2.设置signalR的hubs url地址:$.connection.hub.url =xxx
    3.声明一个代理对象来引用集线器:var chat = $.connection.dntHub;
    4.创建一个客户端方法:chat.client.xxxx=function(){}
    5.启动并调用服务端方法:
        $.connection.hub.start().done(function(){
            chat.server.xxx()
        });
    -->

代码贴起:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>简单聊天程序</title>
    <style type="text/css">
        .container {
            background-color: #99CCFF;
            border: thick solid #808080;
            padding: 20px;
            margin: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <input type="text" id="message" />
        <input type="button" id="sendmessage" value="Send" />
        <input type="hidden" id="displayname" />
        <ul id="discussion"></ul>
    </div>
    <script src="Scripts/jquery-1.8.3.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.0.js"></script>
    <!--动态生成的-->
    <script src="http://localhost:5438/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            //日记记录
            $.connection.hub.logging = true;
 
            //设置hubs的url
            $.connection.hub.url = "http://localhost:5438/signalr";
 
            // 声明一个代理来引用该集线器。
            var chat = $.connection.dntHub;
 
            // 创建一个方法供服务端调用
            chat.client.addMessage = function (name, message) {
                var encodedName = $('<div />').text(name).html();
                var encodedMsg = $('<div />').text(message).html();
                $('#discussion').append('<li><strong>' + encodedName + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
            };
            $('#displayname').val('路人');
 
            // 启动 connection
            $.connection.hub.start().done(function () {
                $('#sendmessage').click(function () {
                    //调用服务器端方法
                    chat.server.serviceSend($('#displayname').val(), $('#message').val());
                });
            });
        });
    </script>
    <!--
    总结一下:
    1.先引入jq包,再引入signalR的js包,再引入signalR动态生成的hubs
    2.设置signalR的hubs url地址:$.connection.hub.url =xxx
    3.声明一个代理对象来引用集线器:var chat = $.connection.dntHub;
    4.创建一个客户端方法:chat.client.xxxx=function(){}
    5.启动并调用服务端方法:
        $.connection.hub.start().done(function(){
            chat.server.xxx()
        });
    -->
</body>
</html>

如果要调试的话,保证服务端先运行,调试小技巧:

下面说一下上面的好处:

webclient我就单独拿出来了(一个js包,一个index.html),控制台的程序我也单独拿出来了,下面先运行一下服务端,再打开index.html

再次验证最上面说的,端口不固定

第二个阶段:

QQ聊天案例,先讲一种常规的方法,下面会讲一种简单方法

先看看gif效果图把

定义一个BaseHub类,里面用 qqModeList来临时存放数据(用户数据)

QQModel,目前就用到两个属性,其他的可以自己扩展

定义了一个上线方法,一会每个客户端都会调用(本来是准备用OnConnected的,没办法他没参数。。。而且这个时候,qq昵称还没有产生,于是我取其次的方案)

定义一个发消息的方法

下面就是前端的东西了,注释很详细,不清楚可以直接留言,我没高兴深度封装,主要就是简单演示一下

代码贴上:

客户端-逆天

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>仿QQ聊天--我是逆天</title>
    <link href="Style/MyQQ.css" rel="stylesheet" />
</head>
<body>
    <div><input id="inputMsg" /><input id="btn" type="button" value="发消息" /></div><br /><br />
    <div id="main"></div>
 
    <script src="Scripts/jquery-2.2.1.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="http://localhost:5438/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            var leftHtml = [
                '<div class="sender">',
                '<div><img src="http://img.jfdown.com/jfdown/201403/ygald3wajct.jpg"></div>',
                '<div><div class="left_triangle"></div>',
                '<span>{msg}</span></div></div>'
            ].join('');
 
            var rightHtml = [
                '<div class="receiver">',
                '<div><img src="http://tb.himg.baidu.com/sys/portrait/item/306c9328?t=1397975854"></div>',
                '<div><div class="right_triangle"></div>',
                '<span>{msg}</span></div></div>'
            ].join('');
 
            //设置hubs的url
            $.connection.hub.url = 'http://localhost:5438/signalR';
            // 声明一个代理
            var qqProxy = $.connection.qQHub;
            // 创建一个方法供服务端调用
            qqProxy.client.sendMsg = function (msg) {
                $('#main').append(leftHtml.replace('{msg}', msg));
            }
            // 启动 connection
            $.connection.hub.start().done(function () {
                qqProxy.server.online('逆天');//QQ昵称
                $('#btn').click(function () {
                    //获取输入
                    var qqmsg = $('#inputMsg').val();
                    //给逆天发消息
                    qqProxy.server.serviceSend('妹子', qqmsg);
                    $('#main').append(rightHtml.replace('{msg}', qqmsg));
                });
            });
        });
    </script>
</body>
</html>

客户端-美女

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>仿QQ聊天--我是美女</title>
    <link href="Style/MyQQ.css" rel="stylesheet" />
</head>
<body>
    <div><input id="inputMsg" /><input id="btn" type="button" value="发消息" /></div><br /><br />
    <div id="main"></div>
 
    <script src="Scripts/jquery-2.2.1.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="http://localhost:5438/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            var rightHtml = [
                '<div class="sender">',
                '<div><img src="http://img.jfdown.com/jfdown/201403/ygald3wajct.jpg"></div>',
                '<div><div class="left_triangle"></div>',
                '<span>{msg}</span></div></div>'
            ].join('');
 
            var leftHtml = [
                '<div class="receiver">',
                '<div><img src="http://tb.himg.baidu.com/sys/portrait/item/306c9328?t=1397975854"></div>',
                '<div><div class="right_triangle"></div>',
                '<span>{msg}</span></div></div>'
            ].join('');
 
            //设置hubs的url
            $.connection.hub.url = 'http://localhost:5438/signalR';
            // 声明一个代理
            var qqProxy = $.connection.qQHub;
            // 创建一个方法供服务端调用
            qqProxy.client.sendMsg = function (msg) {
                $('#main').append(leftHtml.replace('{msg}',  msg));
            }
            // 启动 connection
            $.connection.hub.start().done(function () {
                qqProxy.server.online('妹子');//QQ昵称
                $('#btn').click(function () {
                    //获取输入
                    var qqmsg = $('#inputMsg').val();
                    //给逆天发消息
                    qqProxy.server.serviceSend('逆天', qqmsg);
                    $('#main').append(rightHtml.replace('{msg}', qqmsg));
                });
            });
        });
    </script>
</body>
</html>

第三阶段

群发

我们先接着昨天的QQ聊天来说

这次用一个简单的方法搞定

一个键值对集合存放ConnectionId和GroupName

每个客户端连接的时候会加入一个组

 断开的时候退出组

 发消息

前端也进行了优化。ok,signalR第三个demo诞生,比昨天简单多了

下面可以说说类似于QQ群的群发消息了

这个是逆天的自学笔记:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/31064.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【面试】标准库相关题型(二)

文章目录 1. deque底层实现原理1.1 概述1.2 原理图1.3 类结构1.4 操作函数 2. 什么时候使用vector、list、deque2.1 vector2.2 list2.3 deque 3. priority_queue的底层实现原理3.1 一句话概括&#xff1a;用堆来实现优先级队列3.2 堆结构3.3 底层容器3.4 STL对堆结构提供的接口…

Java-API简析_java.lang.SecurityManager类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131346082 出自【进步*于辰的博客】 其实我的【Java-API】专栏内的博文对大家来说意义是不大的。…

Python入门(二十七)测试(二)

测试&#xff08;二&#xff09; 1.测试类2.各种断言方法3.一个要测试的类4.测试AnonymousSurvey类5.方法setUp() 1.测试类 前面我们编写了针对单个函数的测试&#xff0c;下面来编写针对类的测试。很多程序中都会用到类&#xff0c;因此证明我们的类能够正确工作大有裨益。如…

学了那么长时间的编程,C语言的各种操作符都搞不懂?点开这里有详细的介绍—>

目录 前言 一、原码、反码、补码的基础概念 1.原码 2.反码 3.补码 二、原码、反码、补码的计算方法 1.原码 2.反码 3.补码 三、算术操作符 四、移位操作符 1. 左移操作符 移位规则&#xff1a; 2. 右移操作符 移位规则&#xff1a; &#xff08;1&#xff09; …

电脑怎么录屏?推荐2款录制电脑屏幕的软件!

案例&#xff1a;我经常需要把电脑上的内容分享给别人&#xff0c;一般通过手机拍摄的方式。这就导致视频十分模糊&#xff0c;给人的观感不太好&#xff0c;有没有什么方法可以实现在电脑上直接录屏&#xff1f; 【我想录制我的电脑屏幕上的内容分享给别人&#xff0c;但是我…

几个SQL的高级写法

一、ORDER BY FLELD() 自定义排序逻辑 MySql 中的排序 ORDER BY 除了可以用 ASC 和 DESC&#xff0c;还可以通过 ORDER BY FIELD(str,str1,...) 自定义字符串/数字来实现排序。这里用 order_diy 表举例&#xff0c;结构以及表数据展示&#xff1a; ORDER BY FIELD(str,str1,..…

【Neo4j教程之CQL函数基本使用】

&#x1f680; Neo4j &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;C…

3d重建+神经渲染

3d重建 基于深度相机(结构光、TOF、双目摄像头)的三维重建基于图像的三维重建&#xff1a;深度学习基于视觉几何的传统三维重建&#xff1a;这种三维重建方法研究时间比较久远&#xff0c;技术相对成熟。主要通过多视角图像对采集数据的相机位置进行估计&#xff0c;再通过图像…

一种对不同类型齐格勒-尼科尔斯 P-I-D 控制器调谐算法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

常用工具类之AJ-Captcha入门

1.引入MAVEN依赖 若依官方引入的是1.2.7版本。我选择了目前最常用的1.3.0版本。 在项目中给的 ruoyi-framework\pom.xml 添加依赖 <!-- anji滑块验证码 --><dependency><groupId>com.anji-plus</groupId><artifactId>spring-boot-starter-captc…

通过调整图像hue值并结合ImageEnhance库以实现色调增强

前言 PIL库中的ImageEnhance类可用于图像增强&#xff0c;可以调节图像的亮度、对比度、色度和锐度。 通过RGB到HSV的变换加调整可以对图像的色调进行调整。 两种方法结合可以达到更大程度的图像色调增强。 调整hue值 __author__ TracelessLe __website__ https://blog…

vue2中引入天地图及相关配置

前言 项目中需要引入特殊用途的地图&#xff0c;发现天地图比高德地图、百度地图要更符合需求&#xff0c;于是看了看天地图。 正文 vue2项目中如何引入天地图并对相关的配置进行修改使用呢&#xff1f;官方给的4.0版本的使用说明。 引入&#xff1a; 进入到public/index.html中…

Cocos Creator3D:制作可任意拉伸的 UI 图像

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 制作可任意拉伸的 UI 图像 UI 系统核心的设计原则是能够自动适应各种不同的设备屏幕尺寸&#xff0c;因此我们在制作 UI 时需要正确设置每个控件元素的尺寸&#xff08;size&#…

TypeScript ~ TS 掌握自动编译命令 ③

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; TypeScript ~ TS &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &…

【CV 向】OpenCV 图形绘制指南

文章目录 引言1. 创建画布2. 绘制线段3. 绘制矩形4. 绘制圆5. 绘制椭圆6. 绘制多边形7. 绘制字体结论 引言 Python OpenCV 是一个功能强大的计算机视觉库&#xff0c;除了图像处理和计算机视觉任务外&#xff0c;它还提供了丰富的功能来绘制各种图形。无论是在计算机视觉应用中…

Springboot程序开启远程DEBUG

一、远程debug的原理 Spring Boot程序远程debug的原理主要是通过在启动时指定JVM参数来启用远程调试模式&#xff0c;并在调试器中连接到程序所在的调试地址&#xff0c;从而实现对程序的远程调试。 具体步骤如下&#xff1a; 在运行Spring Boot程序时&#xff0c;在启动命令…

软考高级系统架构设计师(四) 计算机网络2磁盘阵列

目录 磁盘阵列RAID RAID级别 ​IPV6 网络接入技术 综合布线 磁盘阵列RAID 磁盘阵列&#xff08;Redundant Arrays of Independent Disks&#xff0c;RAID&#xff09;&#xff0c;有"数块独立磁盘构成具有冗余能力的阵列”之意。 磁盘阵列是由很多块独立的磁盘&#…

P35[10-5]硬件IIC配置+读写MPU6050(软)(此处注意与软件iic区别)

接线图如下: 注:硬件读写iic的连接位置固定,可参考引脚定义表(如下) 声明:I2C1重映射时,有一次更换机会,但是此面包板由于OLED的该引脚无法接线,因此只能接在PB10 PB11的I2C2上 软件iic初始化部分:(此处即可替代掉整个软件iic.c初始化的底层) void MPU6050_Init(vo…

MyCat总结

目录 什么是mycat 核心概念 逻辑库 逻辑表 分片节点 数据库主机 用户 mycat原理 目录结构 配置文件 读写分离 搭建读写分离 搭建主从复制&#xff1a; 搭建读写分离&#xff1a; 分片技术 垂直拆分 实现分库&#xff1a; 水平拆分 实现分库&#xff1a; ER表 全局表 分…

IDEA新UI速览,成了VS Code的样子?

IntelliJ IDEA 2023.1 现已发布。此版本包括对新 UI 的改进&#xff0c;根据从用户那里收到的反馈进行了彻底改造。此外还实现了性能增强&#xff0c;从而在打开项目时更快地导入 Maven 和更早地使用 IDE 功能。由于采用了 background commit checks&#xff0c;新版本提供了简…