ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。(来自官方介绍。)

SignalR官网

-1、写这篇的原因

在上篇文章B/S(Web)实时通讯解决方案中,并没有详情介绍SignalR,所以另起一篇专门介绍SignalR,本文的侧重点是Hub功能。

0、先看最终实现效果

github:https://github.com/Emrys5/SignalRGroupChatDemo

在线演示:http://chat.lining.name/

1、准备工作

1.1、在NuGet上首先下载SignalR的包。

1.2、配置Owin与SignalR

1.2.1、新建Startup类,注册SignalR

1 public class Startup
2     {
3         public void Configuration(IAppBuilder app)
4         {
5             app.MapSignalR();
6         }
7     }

然后在web.config配置Startup类,在configuration=>appSettings节点中添加

<add key="owin:AppStartup" value="SignalRChat.App_Start.Startup"/>

1.2.2、在页面引入SignalR的js

1、由于SignalR前端是基于jQuery的,所以页面需引入jQuery。

2、引入SignalR的js 。

3、引入最重要的hubs js,这个js其实并不存在,SignalR会反射获取所有供客户端调用的方法放入hubs js中。

<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="~/signalr/hubs"></script>

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)

客户端代码

<script  type="text/javascript">  var ticker = $.connection.simpleHub;$.connection.hub.start();$("#btn").click(function () {// 链接完成以后,可以发送消息至服务端ticker.server.sendMsg("需要发送的消息");});</script>

服务端代码

  [HubName("simpleHub")]public class SimpleHub : Hub{public void SendMsg(string msg){// 获取链接idvar connectionId = Context.ConnectionId; // 获取cookievar cookie = Context.RequestCookies;}}

其中SimpleHub就是我们定义的继承HubSimpleHub,然后我们可以用特性HubName进行重命名。

然后开始链接。

在链接完成以后,我们就可以调用在SimpleHub类中调用的方法。这就就很简单的实现了客户端至服务端发送消息。

我们还可以在Context中获取我们想要的东西,比如链接id,cookie等。

2.2、服务端至客户端(S=>B)

服务端代码

 [HubName("simpleHub")]public class SimpleHub : Hub{public void SendMsg(string msg){Clients.All.msg("发送给客户端的消息"); }}

客户端代码

<script type="text/javascript">var ticker = $.connection.groupChatHub;$.connection.hub.start();ticker.client.msg = function (data) {console.log(data);}
</script>

这里演示了怎么发送消息至客户端,也是SignalR比较重要的功能,这里有两个问题需要解决。

问题一、这里是发送消息给所有连着的客户端,如果是单个客户端或者是一批客户端应该怎么发送。

问题二、我们在调用msg给个客户端发送消息时是在接收消息以后做的反馈,然后发送消息给客户端,这样就很类似ajax了,服务端并没有主动给客户端发送消息。

解决:

问题一、Clients可以给特性的一群或者一个客户端发送消息

       // 所有人Clients.All.msg("发送给客户端的消息");  // 特定 cooectionIdClients.Client("connectionId").msg("发送给客户端的消息");// 特定 groupClients.Group("groupName").msg("发送给客户端的消息");

这是比较常用的三个,当然还有很多,比如AllExcept,Clients。

在SignalR2.0中还添加了Others,OthersInGroup,OthersInGroups等等。

问题二、我们可以在需要发送消息的地方调用GlobalHost.ConnectionManager.GetHubContext<SimpleHub>().Clients中获取Clients。获取Clients并发送消息我们最好写成单例模式,因为这种需求很符合单例,群聊中有详细的代码。

3、SignalR实现群聊

以上的介绍和代码已经可以实现b=>s和s=>b了,那实现群聊和单独聊天就比较简单了。

由于功能比较简单,所有我把用户名存到了cookie里,也就说第一次进来时需要设置cookie。

还有就是在hub中要实现OnConnectedOnDisconnectedOnReconnected,然后在方法中设置用户和connectionid和统计在线用户,以便聊天使用。

hub代码

/// <summary>/// SignalR Hub 群聊类/// </summary>[HubName("groupChatHub")] // 标记名称供js调用public class GroupChatHub : Hub{/// <summary>/// 用户名/// </summary>private string UserName{get{var userName = Context.RequestCookies["USERNAME"];return userName == null ? "" : HttpUtility.UrlDecode(userName.Value);}}/// <summary>/// 在线用户/// </summary>private static Dictionary<string, int> _onlineUser = new Dictionary<string, int>();/// <summary>/// 开始连接/// </summary>/// <returns></returns>public override Task OnConnected(){Connected();return base.OnConnected();}/// <summary>/// 重新链接/// </summary>/// <returns></returns>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);}/// <summary>/// 结束连接/// </summary>/// <param name="stopCalled"></param>/// <returns></returns>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 GroupGroups.Remove(Context.ConnectionId, "GROUP-" + UserName);return base.OnDisconnected(stopCalled);}/// <summary>/// 发送消息,供客户端调用/// </summary>/// <param name="user">用户名,如果为0,则是发送给所有人</param>/// <param name="msg">消息</param>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<string> { "GROUP-" + UserName, "GROUP-" + user }).publshMsg(FormatMsg(UserName, msg));}}/// <summary>/// 格式化发送的消息/// </summary>/// <param name="name"></param>/// <param name="msg"></param>/// <returns></returns>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代码

<script type="text/javascript">$(function () {// 链接hubvar ticker = $.connection.groupChatHub;$.connection.hub.start();// 接收服务端发送的消息
            $.extend(ticker.client, {// 接收聊天消息
                publshMsg: function (data) {$("#msg").append("<li><span class='p'>" + data.Name + ":</span>" + data.Msg + " <span class='time'>" + data.Time + "</span></li>")$("#msg").parents("div")[0].scrollTop = $("#msg").parents("div")[0].scrollHeight;},// 接收在线人员,然后加入Select,以供单独聊天选中
                publshUser: function (data) {$("#count").text(data.length);$("#users").empty();$("#users").append('<option value="0">所有人</option>');for (var i = 0; i < data.length; i++) {$("#users").append('<option value="' + data[i] + '">' + data[i] + '</option>')}}});// 发送消息按钮$("#btn-send").click(function () {var msg = $("#txt-msg").val();if (!msg) {alert('请输入内容!'); return false;}$("#txt-msg").val('');// 主动发送消息,传入发送给谁,和发送的内容。ticker.server.sendMsg($("#users").val(), msg);});});</script>

html代码

<h2>群聊系统(<span id="count">1</span>人在线):@ViewBag.UserName
</h2><div style="overflow:auto;height:300px"><ul id="msg"></ul>
</div><select id="users" class="form-control" style="max-width:150px;"><option value="0">所有人</option>
</select><input type="text" οnkeydοwn='if (event.keyCode == 13) { $("#btn-send").click() }' class="form-control" id="txt-msg" placeholder="内容" style="max-width:400px;" />
<br />
<button type="button" id="btn-send">发送</button>

这样就消息了群聊和发送给特定的人聊天功能。

3.1、封装主动发送消息的单例

/// <summary>/// 主动发送给用户消息,单例模式/// </summary>public class GroupChat{/// <summary>/// Clients,用来主动发送消息/// </summary>private IHubConnectionContext<dynamic> Clients { get; set; }private readonly static GroupChat _instance = new GroupChat(GlobalHost.ConnectionManager.GetHubContext<GroupChatHub>().Clients);private GroupChat(IHubConnectionContext<dynamic> clients){Clients = clients;}public static GroupChat Instance{get{return _instance;}}/// <summary>/// 主动给所有人发送消息,系统直接调用/// </summary>/// <param name="msg"></param>public void SendSystemMsg(string msg){Clients.All.publshMsg(new { Name = "系统消息", Msg = msg, Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") });}}

如果需要发送消息,直接调用SendSystemMsg即可。

GroupChat.Instance.SendSystemMsg("消息");

4、结语

啥也不说了直接源码

github:https://github.com/Emrys5/SignalRGroupChatDemo

在线演示:http://chat.lining.name/

最后望对各位有所帮助,本文原创,欢迎拍砖和推荐

Asp.net SignalR 应用并实现群聊功能 开源代码相关推荐

  1. 互联网早报 | 3月16日 星期二 | 微信AI直播助理开放内测;汽车之家港交所挂牌上市;美团App内测“群聊”功能...

    今日看点 ✦ 汽车之家港交所成功挂牌,成年内首家回港二次上市中概股 ✦ 恒大汽车与腾讯旗下梧桐车联成立合资公司 ,共同开发车载智能操作系统 ✦ 微信AI直播助理开放内测,助力电商带货 ✦ 美团App内 ...

  2. 360搜索、UC浏览器等被3·15点名应用已下架;马斯克宣布通过NFT卖歌;美团App再发力社交,内测 “群聊”功能 |极客头条...

    「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧. 整理 | 丁恩华 出品 | CSDN(ID:CSDNnews ...

  3. C++搭建集群聊天室(十四):群聊功能

    文章目录 群聊功能思路 放码过来 groupuser.hpp group.hpp groupmodel.hpp groupmodel.cpp 群聊功能思路 1.创建群聊,提交群信息,返回群号 2.拉取 ...

  4. Line推出新语音群聊功能 最多支持200人

    3月11日,据科技博客VentureBeat报道,日本移动通讯巨头Line公司近日宣布,为支持企业电话会议,该公司将在最新版Line应用中增加语音群聊功能,最多支持200人同时群聊. Line的这项新 ...

  5. 基于WebSocket实现一个简易的群聊功能

    本文主要来讲解如何使用WebSocket来实现一个简易的群聊功能 引入maven依赖 <dependency><groupId>org.springframework.boot ...

  6. 360搜索、UC浏览器等被3·15点名应用已下架;马斯克宣布通过NFT卖歌;美团App再发力社交,内测 “群聊”功能...

    凌云时刻 一分钟速览新闻点! 猎聘.前程无忧为大量简历流向黑市而致歉 医疗广告竞价排名,360 搜索.UC 纷纷上榜 315 晚会 315 晚会曝光人脸识别乱象:海量人脸信息已被搜集 安兔兔曝光 re ...

  7. android微信群聊功能,微信安卓内测更新,这个群聊功能等了8年

    近日,安卓版微信悄然迎来了 8.0.3 内测版更新,本次内测又带来了哪些新功能呢,一起来看看吧. 01 群聊支持键入 @所有人 微信作为国民级应用,而微信群又是微信中的一个重要组成部分." ...

  8. 小程序集成网易云通信群聊功能Demo发布

    前端代码是可以直接使用的,获取后端代码加微信13439975582 功能实现说明: 1.小程序生命周期完美整合 2.消息小红点,群聊小红点代码实现都实现了 3.历史信息回放 4.小程序帐号集成 代码都 ...

  9. 基于Vue+springboot+websocket实现的简短仿微信web聊天室(私聊和群聊功能)(可在线预览)

    写目录 一.界面展示 二.介绍 一.界面展示 之前闲着有空就给自己的个人博客搭了一些附加功能,聊天室也是其中之一,简单的实现了私聊.群聊功能,可以发送emoji表情和图片等,项目已经部署在www.tc ...

最新文章

  1. SQLSTATE[HY000] [2003] Can’t connect to MySQL serv
  2. 信息系统管理十大知识领域
  3. Dcloud+mui 压缩上传图片到服务器
  4. 匹配嵌套的构造(较复杂)
  5. 保存工具条菜单有bug吗?
  6. wordpress迁移后,伪静态404解决方法
  7. PSD分层模板素材|电商页面这样设计,转化率成倍提高!
  8. 【Python-3.5】win7安装Pygame
  9. 关于使用 autoFac 的注入方法
  10. [cogs] 传染病控制
  11. linux wqy字体安装,给openSUSE安装文泉驿字体
  12. 【必备知识】摄像机标定基础理论
  13. workbench动力学周炬_ANSYSWorkbench有限元分析实例详解(动力学)
  14. 【URLOS应用开发基础】10分钟制作一个nginx静态网站环境应用
  15. 建设银行和工商银行的网银安全措施
  16. python重复import_Python 中循环 import 造成的问题如何解决?
  17. macbook air 卸载java,macbook air如何删除程序
  18. Unity Addressable学习笔记二(Hosting热更新)
  19. excel单元格斜线_含金量100%的9个Excel函数公式,全部100%掌握的都是超级高手!...
  20. 计算机组成原理 总线与微命令实验

热门文章

  1. 本人CCNP、OCP MCSA 证书寻求挂靠
  2. HDU 4286 Data Handler [栈,双端队列]
  3. C++中string查找和取子串和整形转化
  4. spring获取bean的方案
  5. Scala学习笔记-5
  6. 【阿里云产品公测】高大上的搜索服务OpenSearch, 你值得拥有!
  7. 如何让Linux禁止Ctrl+Alt+Del重启(防止被强行关闭)     erikxue 薛忠权
  8. SysAid 9.0 发布,增加移动设备管理功能
  9. ASP.NET中Visio图形的控制与数据的动态显示
  10. nodejs渐入佳境[27]-express+mongodb+middleware实现密码哈希