ASP.NET SignalR是一个方便程序员添加实时网络通信功能的类库。所谓的实时网络通信功能(Real-time Web Functionality)就是需要服务器主动推送数据到用户客户端,而非服务器等待用户客户端请求数据的功能。以聊天室为例,当一个用户发送群发消息之后,在所有用户的聊天窗口中都需要显示出这条消息,如果每个用户客户端都是用Ajax每隔一定时间去服务器上拉取消息,那样不仅效率低下并增加服务器负担,也不是真正意义上的实时程序。
消息传输机制
ASP.Net SignalR使用新的Websocket传输协议,他实现了浏览器和服务器全双工通信(允许服务器主动发消息给客户端),并兼容以前的长连接(Long poll)传输方式, 所以对于开发人员来说,不需要自己去维护使用何种传输方式,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)
SignalR学习笔记(一) 简单聊天室
替换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);
}
}
}
}
}