SignalR学习笔记(一) 简单聊天室
什么是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的基本使用方式。
这个聊天室页面的需求如下:
- 用户打开聊天室页面,需要首先录入自己的昵称,输入昵称之后,通知聊天室的其他用户该用户进入聊天室
- 用户可以使用在聊天室中发送公共消息
- 用户可以使用“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学习笔记(一) 简单聊天室的更多相关文章
- Asp.Net SignalR - 简单聊天室实现
简单聊天室 使用持久链接类我们就可以做一些即时通讯的应用了,我使用Group做了一个简单的聊天室,先上图技术细节下面再讲 可以加入聊天室.创建聊天室.发送消息,下面就说说我是如何通过Group做出来的 ...
- 简单聊天室(java版)
这是本人从其他地方学习到的关于聊天室的一个模本,我从中截取了一部分关于客户端和服务端通信的Socket的内容.希望对大家对socket有个了解,我写的这些代码可以实现两人或多人在多台电脑上实现简单的对 ...
- JSP学习笔记(三):简单的Tomcat Web服务器
注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...
- Python Socket 简单聊天室2
上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...
- SignalR学习笔记(二)高并发应用
虽然SignalR借助Websocket提供了很强大的实时通讯能力,但是在有些实时通讯非常频繁的场景之下,如果使用不当,还是会导致服务器,甚至客户端浏览器崩溃. 以下是一个实时拖拽方块项目的优化过程 ...
- SpringBoot 搭建简单聊天室
SpringBoot 搭建简单聊天室(queue 点对点) 1.引用 SpringBoot 搭建 WebSocket 链接 https://www.cnblogs.com/yi1036943655/p ...
- ASP.NET SingalR + MongoDB 实现简单聊天室(一):搭建基本框架
ASP.NET SingalR不多介绍.让我介绍不如看官网,我这里就是直接上源代码,当然代码还是写的比较简单的,考虑的也少,希望各位技友多多提意见. 先简单介绍聊天室功能: 用户加入聊天室,自动给用户 ...
- 利用socket.io+nodejs打造简单聊天室
代码地址如下:http://www.demodashi.com/demo/11579.html 界面展示: 首先展示demo的结果界面,只是简单消息的发送和接收,包括发送文字和发送图片. ws说明: ...
- JAVA WEB学习笔记(三):简单的基于Tomcat的Web页面
注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...
随机推荐
- Centos7安装jdk-12的详细过程
Centos7安装jdk-12的详细过程 2019-04-12 21:23:24 一.下载JDK-12版本 链接地址:官方地址 下载:jdk-12_liunx-x64_bin.tar.gz 二.检 ...
- ImCash:币圈英文术语大全
近年来随着数字货币的火热,在全世界范围内涌现出了一群数字货币的“发烧友”和忠实投资者,他们形成了自己的圈子“币圈”,并且有了自己的文化和语言,今天就让我们一起来了解一下外国币圈有哪些有意思的英文“专用 ...
- hdu6489 2018 黑龙江省大学生程序设计竞赛j题
Problem Description Kayaking is playing a puzzle game containing n different blocks. He marks the bl ...
- Codeforces 1144F Graph Without Long Directed Paths (DFS染色+构造)
<题目链接> 题目大意:给定一个无向图,该无向图不含自环,且无重边.现在要你将这个无向图定向,使得不存在任何一条路径长度大于等于2.然后根输入边的顺序,输出构造的有向图.如果构造的边与输入 ...
- 【nuget】PackageReference
.net 爬虫 <PackageReference Include="HtmlAgilityPack" Version="1.9.0" /> < ...
- git cannot lock ref
参考博客:https://blog.csdn.net/lindexi_gd/article/details/79213042 错误原文: cannot lock ref ‘refs/remotes/o ...
- MyBatis3系列__04CRUD以及参数处理
本文将会简单介绍一下MyBatis的CRUD以及结合源码讲解一下MyBatis对参数的处理. 作为一个ORM框架,最基本的使用也就是CRUD了,MyBatis提供了两种方法:xml配置文件和动态注解. ...
- Shell 编程注意点
(一)判断语句 [$# -lt 4 ]判断语句,格式[空格 比较对象1 比较符号 比较对象2] $# 启动脚本时携带参数个数;参数个数总数. $1 代表第一个参数. $? 最后一次执行名命令的退出状态 ...
- 网站 Cookie only 唯一 防止被截获
void Page_Load(object sender, EventArgs e) { // Create a new HttpCookie. HttpCookie myHttpCookie = n ...
- Qt5和VS2017建立开发环境,安装后新建项目找不到Qt选项!!!
最近开发win驱动和Qt5测试程序,需要建立Qt5和VS2017开发环境---对于Qt5和VS2017安装这里不做多余叙述. 参考资源很多,讲解也不错!! 这里切入正题:在VS2017中安转Qt vs ...

