什么是ASP.NET SignalR?

ASP.NET SignalR是一个方便程序员添加实时网络通信功能的类库。所谓的实时网络通信功能(Real-time Web Functionality)就是需要服务器主动推送数据到用户客户端,而非服务器等待用户客户端请求数据的功能。以聊天室为例,当一个用户发送群发消息之后,在所有用户的聊天窗口中都需要显示出这条消息,如果每个用户客户端都是用Ajax每隔一定时间去服务器上拉取消息,那样不仅效率低下并增加服务器负担,也不是真正意义上的实时程序。

消息传输机制

ASP.Net SignalR使用新的Websocket传输协议,他实现了浏览器和服务器全双工通信(允许服务器主动发消息给客户端),并兼容以前的长连接(Long poll)传输方式, 所以对于开发人员来说,不需要自己去维护使用何种传输方式,SignalR会自动根据客户端浏览器的版本自动切换消息传输方式

  • 对于IE8,会自动切换到Long poll传输。
  • 对于IE9及以上版本,会使用Websocket传输。

连接与枢纽

SignalR API包含2个模型来帮助客户端与服务器进行通信: 持久连接(Persistent Connections)与枢纽 (hubs).

持久连接负责传输消息,枢纽提供了一种很有趣的机制,允许开发人员在客户端调用服务器端方法或服务器端调用客户端方法。

枢纽(Hubs)是如何工作的

当服务器端程序调用客户端方法时,一个包含客户端方法名及参数的Json数据包会通过持久连接传输到客户端,客户端会根据数据包中的方法名进行匹配,如果找到相同方法名的方法,就会自动调用找到的方法,方法所需的参数值会使用数据包中对应的参数值。

简单的聊天室

下面用一个聊天室的例子,熟悉一下SignalR的基本使用方式。

这个聊天室页面的需求如下:

  1. 用户打开聊天室页面,需要首先录入自己的昵称,输入昵称之后,通知聊天室的其他用户该用户进入聊天室
  2. 用户可以使用在聊天室中发送公共消息
  3. 用户可以使用“to 用户名 消息内容”的方式发送私聊消息

添加项目

新建一个空的ASP.NET Web Application工程


通过Nuget或者最新版本的SignalR库

展开Package Manager Console面板,输入

install-package Microsoft.AspNet.SignalR

添加Startup.cs启用SignalR

using Microsoft.Owin;

using Owin;

 

[assembly: OwinStartup(typeof(ChatRoom.Startup))]

 

namespace ChatRoom

{

    public class Startup

    {

        public void Configuration(IAppBuilder app)

        {

            //启用SignalR

            app.MapSignalR();

        }

    }

}

添加枢纽(Hub)

在工程中添加ChatRoomHub.cs, 选择SignalR Hub Class(v2)

替换ChatRoomHub类中的内容替换

using Microsoft.AspNet.SignalR;

using System.Collections.Generic;

using System.Linq;

 

namespace ChatRoom

{

    public class ChatRoomHub : Hub

    {

        private static Dictionary<string, string> _nickNames = new Dictionary<string, string>();

 

        public void SetNickName(string nickName)

        {

            //当Hub启动完毕,每个连接到这个Hub的客户端都会自动分配一个唯一的ConnectionId。

            //当SignalR向指定客户端推送消息的时候,需要指定ConnectionId, 所以这里需要记录一下每个昵称对应的客户端ConnectionId

            _nickNames.Add(Context.ConnectionId, nickName);

 

            //当用户设置昵称之后,需要发送欢迎信息到所有的用户客户端,调用客户端receiveWelcomeMessage方法显示欢迎信息

            Clients.All.ReceiveWelcomeMessage($"{nickName}进入聊天室。");

        }

 

        public void Send(string nickName, string message)

        {

            if (string.IsNullOrWhiteSpace(nickName) || string.IsNullOrWhiteSpace(message))

            {

                //如果用户昵称或者消息不存在,就不做任何操作

                return;

            }

 

            if (message.StartsWith("to") && message.Split(' ').Length == 3)

            {

                //私聊消息

                var toUserName = message.Split(' ')[1];

 

                if (_nickNames.ContainsValue(toUserName))

                {

                    var connectionId = _nickNames.First(p => p.Value == toUserName).Key;

 

                    if (!string.IsNullOrWhiteSpace(connectionId) && connectionId != Context.ConnectionId)

                    {

                        Clients.Client(connectionId).ReceivePrivateMessage(nickName, message.Split(' ')[2]);

                    }

                }

            }

            else

            {

                //普通广播消息

                if (_nickNames.ContainsValue(nickName))

                {

                    Clients.All.ReceiveBroadcastMessage(nickName, message);

                }

            }

        }

    }

}

添加显示页面

添加空html文件ChatRoom.html, 使用以下文件替换

<!DOCTYPE html>

<html>

<head>

    <title>SignalR Simple Chat</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.6.4.min.js"></script>

    <script src="Scripts/jquery.signalR-2.2.2.min.js"></script>

    <script src="signalr/hubs"></script>

 

    <script type="text/javascript">

        $(function () {

 

            //使用代理模式, 创建客户端的hub代理

            var chat = $.connection.chatRoomHub;

 

            //服务器Hub中, 调用ReceiveWelcomeMessage方法时, 会执行客户端的chat.client.receiveBroadcastMessage方法

            chat.client.receiveBroadcastMessage = function (name, message) {

 

                //防JS输入

                var encodedName = $('<div />').text(name).html();

                var encodedMsg = $('<div />').text(message).html();

 

                $('#discussion').append('<li><strong>' + encodedName

                    + '</strong>:  ' + encodedMsg + '</li>');

            };

 

            //服务器Hub中, 调用ReceiveWelcomeMessage方法时, 会执行客户端的chat.client.receiveWelcomeMessage方法

            chat.client.receiveWelcomeMessage = function (message) {

                var encodedMsg = $('<div />').text(message).html();

 

                $('#discussion').append('<li><strong style="color:blue">' + encodedMsg

                    + '</strong></li>');

            };

 

            //服务器Hub中, 调用ReceivePrivateMessage方法时, 会执行客户端的chat.client.receivePrivateMessage方法

            chat.client.receivePrivateMessage = function (name, message) {

                var encodedName = $('<div />').text(name).html();

                var encodedMsg = $('<div />').text(message).html();

 

                $('#discussion').append('<li><strong style="color: green">' + encodedName

                    + '偷偷的跟你说</strong>:  ' + encodedMsg + '</li>');

            };

 

            //通过代理连接到服务器Hub

            $.connection.hub.start().done(function () {

                $('#sendmessage').click(function () {

                    chat.server.send($('#displayname').val(), $('#message').val());

 

                    $('#message').val('').focus();

                });

 

                //连接成功后, 需要用户立刻输入昵称

                $('#displayname').val(prompt('Enter your name:', ''));

                chat.server.setNickName($('#displayname').val());

                $('#message').focus();

            });

        });

    </script>

</body>

</html>

最终实现效果

SignalR学习笔记(一) 简单聊天室的更多相关文章

  1. Asp.Net SignalR - 简单聊天室实现

    简单聊天室 使用持久链接类我们就可以做一些即时通讯的应用了,我使用Group做了一个简单的聊天室,先上图技术细节下面再讲 可以加入聊天室.创建聊天室.发送消息,下面就说说我是如何通过Group做出来的 ...

  2. 简单聊天室(java版)

    这是本人从其他地方学习到的关于聊天室的一个模本,我从中截取了一部分关于客户端和服务端通信的Socket的内容.希望对大家对socket有个了解,我写的这些代码可以实现两人或多人在多台电脑上实现简单的对 ...

  3. JSP学习笔记(三):简单的Tomcat Web服务器

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

  4. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  5. Python Socket 简单聊天室2

    上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  6. SignalR学习笔记(二)高并发应用

    虽然SignalR借助Websocket提供了很强大的实时通讯能力,但是在有些实时通讯非常频繁的场景之下,如果使用不当,还是会导致服务器,甚至客户端浏览器崩溃. 以下是一个实时拖拽方块项目的优化过程 ...

  7. SpringBoot 搭建简单聊天室

    SpringBoot 搭建简单聊天室(queue 点对点) 1.引用 SpringBoot 搭建 WebSocket 链接 https://www.cnblogs.com/yi1036943655/p ...

  8. ASP.NET SingalR + MongoDB 实现简单聊天室(一):搭建基本框架

    ASP.NET SingalR不多介绍.让我介绍不如看官网,我这里就是直接上源代码,当然代码还是写的比较简单的,考虑的也少,希望各位技友多多提意见. 先简单介绍聊天室功能: 用户加入聊天室,自动给用户 ...

  9. 利用socket.io+nodejs打造简单聊天室

    代码地址如下:http://www.demodashi.com/demo/11579.html 界面展示: 首先展示demo的结果界面,只是简单消息的发送和接收,包括发送文字和发送图片. ws说明: ...

  10. JAVA WEB学习笔记(三):简单的基于Tomcat的Web页面

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

随机推荐

  1. 解决使用redis作为session缓存 报错 Error: no such key 的问题

    spring的issue https://github.com/spring-projects/spring-session/issues/954 原答案是 Updated my codes to 2 ...

  2. leetcode刷题第三天<无重复字符的最长子串>

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 : 输入: "abcabcbb" 输出: 解释: 因为无重复字符的最长子串是 . 示例 : 输入: &quo ...

  3. h5适配的解决方案

    一. 流程 设计师以750pt×1334pt尺寸进行设计(当然高度随内容变化),最后用该尺寸的设计稿进行标注.切图,前端采用淘宝的开源方案flexible进行适配. 二. flexible使用方法 F ...

  4. ASP.NET MVC 网页应用 action 传递的Model

    视图界面 @using {引用模型} @model {具体模型} <html> @Model.{具体模型的属性} </html> 注意区分Model的大小写 引入时,使用@mo ...

  5. SELECT 语句

    常见表的操作 查看数据库的表   show  table 查看表结构     desc 表名 删除表   drop table表 修改表的结构 添加列  alter   table 表名 add 列名 ...

  6. python编程从入门到实战1-3章

    print('hellow world') """ 多行注释"""#大小写print('i love you')mssage='hellow ...

  7. react-native 常用的一些插件

    react-native 常用的一些插件 最近在做react-native的app,用到的一些好用的插件,在这儿记录一下 由于返回的后台内容是富文本编辑器Quill,返回的的是Delta对象,使用了q ...

  8. Python tkinter 学习记录(一) --label 与 button

    最简的形式 from tkinter import * root = Tk() # 创建一个Tk实例 root.wm_title("标题") # 修改标题 root.mainloo ...

  9. FBOSS: Building Switch Software at Scale

    BOSS: 大规模环境下交换机软件构建 本文为SIGCOMM 2018 论文,由Facebook提供. 本文翻译了论文的关键内容. 摘要: 在网络设备(例如交换机和路由器)上运行的传统软件,通常是由供 ...

  10. ubuntu Anaconda install

    在文件目录下执行: bash Anaconda3-4.2.0-Linux-x86_64.sh 根据提示输入回车 这里需要查看注册信息,回车浏览完信息即可 阅读完注册信息后,这里输入“yes” 回车即可 ...