您现在的位置是:网站首页> 编程资料编程资料
Asp.net SignalR应用并实现群聊功能_实用技巧_
2023-05-24
442人已围观
简介 Asp.net SignalR应用并实现群聊功能_实用技巧_
ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。(来自官方介绍。)
-1、写这篇的原因
在上篇文章B/S(Web)实时通讯解决方案中,并没有详情介绍SignalR,所以另起一篇专门介绍SignalR,本文的侧重点是Hub功能。
0、先看最终实现效果

github:https://github.com/Emrys5/SignalRGroupChatDemo
1、准备工作
1.1、在NuGet上首先下载SignalR的包。

1.2、配置Owin与SignalR
1.2.1、新建Startup类,注册SignalR
public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); } }然后在web.config配置Startup类,在configuration=>appSettings节点中添加
1.2.2、在页面引入SignalR的js
1、由于SignalR前端是基于jQuery的,所以页面需引入jQuery。
2、引入SignalR的js 。
3、引入最重要的hubs js,这个js其实并不存在,SignalR会反射获取所有供客户端调用的方法放入hubs js中。
1.2.3、新建GroupChatHub类,并继承Hub抽象类
在hub类中的方法就是提供给客户端调用的js方法。
在js中就可以用signalr调用SendMsg。
[HubName("simpleHub")] public class SimpleHub : Hub { public void SendMsg(string msg) { } } 这样基本上前期准备工作就做完了,后面就是具体的操作。
2、原理与简单的编程
其实原理如果简单点理解就很简单,因为http是无状态的,所以每次请求以后都会与服务器断开链接,那就是说客户端可以很容易找到服务器,但是服务器如果想给你客户端发送消息就比较麻烦,如果不明白的可以参考上一篇文章B/S(Web)实时通讯解决方案。
SignalR就很好的解决了这个问题,也就说实现了实现了浏览器与服务器的全双工通信。
2.1、客户端至服务端(B=>S)
客户端代码
服务端代码
[HubName("simpleHub")] public class SimpleHub : Hub { public void SendMsg(string msg) { // 获取链接id var connectionId = Context.ConnectionId; // 获取cookie var cookie = Context.RequestCookies; } } 其中SimpleHub就是我们定义的继承Hub类SimpleHub,然后我们可以用特性HubName进行重命名。
然后开始链接。
在链接完成以后,我们就可以调用在SimpleHub类中调用的方法。这就就很简单的实现了客户端至服务端发送消息。

我们还可以在Context中获取我们想要的东西,比如链接id,cookie等。
2.2、服务端至客户端(S=>B)
服务端代码
[HubName("simpleHub")] public class SimpleHub : Hub { public void SendMsg(string msg) { Clients.All.msg("发送给客户端的消息"); } } 客户端代码

这里演示了怎么发送消息至客户端,也是SignalR比较重要的功能,这里有两个问题需要解决。
问题一、这里是发送消息给所有连着的客户端,如果是单个客户端或者是一批客户端应该怎么发送。
问题二、我们在调用msg给个客户端发送消息时是在接收消息以后做的反馈,然后发送消息给客户端,这样就很类似ajax了,服务端并没有主动给客户端发送消息。
解决:
问题一、Clients可以给特性的一群或者一个客户端发送消息
// 所有人 Clients.All.msg("发送给客户端的消息"); // 特定 cooectionId Clients.Client("connectionId").msg("发送给客户端的消息"); // 特定 group Clients.Group("groupName").msg("发送给客户端的消息"); 这是比较常用的三个,当然还有很多,比如AllExcept,Clients。
在SignalR2.0中还添加了Others,OthersInGroup,OthersInGroups等等。
问题二、我们可以在需要发送消息的地方调用GlobalHost.ConnectionManager.GetHubContext
3、SignalR实现群聊
以上的介绍和代码已经可以实现b=>s和s=>b了,那实现群聊和单独聊天就比较简单了。
由于功能比较简单,所有我把用户名存到了cookie里,也就说第一次进来时需要设置cookie。
还有就是在hub中要实现OnConnected、OnDisconnected和OnReconnected,然后在方法中设置用户和connectionid和统计在线用户,以便聊天使用。
hub代码
////// SignalR Hub 群聊类 /// [HubName("groupChatHub")] // 标记名称供js调用 public class GroupChatHub : Hub { ////// 用户名 /// private string UserName { get { var userName = Context.RequestCookies["USERNAME"]; return userName == null ? "" : HttpUtility.UrlDecode(userName.Value); } } ////// 在线用户 /// private static Dictionary_onlineUser = new Dictionary (); /// /// 开始连接 /// ///public override Task OnConnected() { Connected(); return base.OnConnected(); } /// /// 重新链接 /// ///public override Task OnReconnected() { Connected(); return base.OnReconnected(); } private void Connected() { // 处理在线人员 if (!_onlineUser.ContainsKey(UserName)) // 如果名称不存在,则是新用户 { // 加入在线人员 _onlineUser.Add(UserName, 1); // 向客户端发送在线人员 Clients.All.publshUser(_onlineUser.Select(i => i.Key)); // 向客户端发送加入聊天消息 Clients.All.publshMsg(FormatMsg("系统消息", UserName + "加入聊天")); } else { // 如果是已经存在的用户,则把在线链接的个数+1 _onlineUser[UserName] = _onlineUser[UserName] + 1; } // 加入Hub Group,为了发送单独消息 Groups.Add(Context.ConnectionId, "GROUP-" + UserName); } /// /// 结束连接 /// /// ///public override Task OnDisconnected(bool stopCalled) { // 人员链接数-1 _onlineUser[UserName] = _onlineUser[UserName] - 1; // 判断是否断开了所有的链接 if (_onlineUser[UserName] == 0) { // 移除在线人员 _onlineUser.Remove(UserName); // 向客户端发送在线人员 Clients.All.publshUser(_onlineUser.Select(i => i.Key)); // 向客户端发送退出聊天消息 Clients.All.publshMsg(FormatMsg("系统消息", UserName + "退出聊天")); } // 移除Hub Group Groups.Remove(Context.ConnectionId, "GROUP-" + UserName); return base.OnDisconnected(stopCalled); } /// /// 发送消息,供客户端调用 /// /// 用户名,如果为0,则是发送给所有人 /// 消息 public void SendMsg(string user, string msg) { if (user == "0") { // 发送给所有用户消息 Clients.All.publshMsg(FormatMsg(UserName, msg)); } else { //// 发送给自己消息 //Clients.Group("GROUP-" + UserName).publshMsg(FormatMsg(UserName, msg)); //// 发送给选择的人员 //Clients.Group("GROUP-" + user).publshMsg(FormatMsg(UserName, msg)); // 发送给自己消息 Clients.Groups(new List{ "GROUP-" + UserName, "GROUP-" + user }).publshMsg(FormatMsg(UserName, msg)); } } /// /// 格式化发送的消息 /// /// /// ///private dynamic FormatMsg(string name, string msg) { return new { Name = name, Msg = HttpUtility.HtmlEncode(msg), Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; } }
js代码
html代码
群聊系统(1人在线):@ViewBag.UserName
这样就消息了群聊和发送给特定的人聊天功能。
3.1、封装主动发送消息的单例
////// 主动发送给用户消息,单例模式 /// public class GroupChat { ////// Clients,用来主动发送消息 /// private IHubConnectionContextClients { get; set; } private readonly static GroupChat _instance = new GroupChat(GlobalHost.ConnectionManager.GetHubContext ().Clients); private GroupChat(IHubConnectionContext clients) { Clients = clients; } public static GroupChat Instance { get { return _instance; } } /// /// 主动给所有人发送消息,系统直接调用 /// /// public void SendSystemMsg(string msg) { Clients.All.publshMsg(new { Name = "系统消息", Msg = msg, Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); } }
相关内容
- ASP.NET MVC制作404跳转实例(非302和200)_实用技巧_
- ASP.NET网站第一次访问慢的解决方法_实用技巧_
- 小心!ASP.NET网站发布时的那些坑_实用技巧_
- asp.net实现多个文件同时下载功能_实用技巧_
- Visual Studio 2017创建.net standard类库编译出错原因及解决方法_实用技巧_
- ASP.NET数据库操作类实例_实用技巧_
- 详解ASP.NET MVC 利用Razor引擎生成静态页_实用技巧_
- 详解ASP.NET MVC 解析模板生成静态页(RazorEngine)_实用技巧_
- ASP.NET防止SQL注入的方法示例_实用技巧_
- ASP.NET实现上传Excel功能_实用技巧_
点击排行
本栏推荐
