ASP.NET SignalR 是为 ASP.NET 开发职员供应的一个库,能够简化开发职员将及时 Web 功用增加到运用程序的历程。及时 Web 功用是指如许一种功用:当所衔接的客户端变得可用时服务器代码能够马上向其推送内容,而不是让服务器守候客户端要求新的数据。(来自官方引见。)
SignalR官网
-1、写这篇的缘由
在上篇文章B/S(Web)及时通讯处置惩罚方案中,并没有概况引见SignalR,所以另起一篇特地引见SignalR,本文的侧重点是Hub功用。
0、先看终究完成结果
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节点中增加
<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) { // 猎取链接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("发送给客户端的音讯"); } }
客户端代码
<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("发送给客户端的音讯"); // 特定 cooectionId Clients.Client("connectionId").msg("发送给客户端的音讯"); // 特定 group Clients.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中要完成OnConnected、OnDisconnected和OnReconnected,然后在要领中设置用户和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 Group Groups.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 () { // 链接hub var 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("p")[0].scrollTop = $("#msg").parents("p")[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> <p style="overflow:auto;height:300px"> <ul id="msg"></ul> </p> <select id="users" class="form-control" style="max-width:150px;"> <option value="0">一切人</option> </select> <input type="text" onkeydown='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.com/Emrys5/SignalRGroupChatDemo
以上就是 Asp.net SignalR的运用并完成群聊功用的实例详解的细致内容,更多请关注ki4网别的相干文章!