本章和人人分享的内容是运用Signal R框架竖立个浅易的群聊功用,主要解说如安在.Net的MVC中运用这个框架,由于这个项目有官方文档(固然全英文),背面也不盘算写分享篇了,主要目标是让朋友们在须要运用Web及时通讯的时刻有更多一种解决方案,毕竟这是微软主推的一种解决方案之一。
SignalR网上简介
ASP.NET SignalR 是为 ASP.NET 开发人员供应的一个库,能够简化开发人员将及时 Web 功用增添到应用顺序的历程。及时 Web 功用是指如许一种功用:当所衔接的客户端变得可用时服务器代码能够马上向其推送内容,而不是让服务器守候客户端请求新的数据。
SignalR固然也供应了异常简朴易用的高阶API,使服务器端能够单个或批量挪用客户端上的JavaScript函数,而且异常 方便地举行衔接治理,比方客户端衔接到服务器端,或断开衔接,客户端分组,以及客户端受权,运用SignalR都异常 轻易完成。
SignalR将与客户端举行及时通讯带给了ASP .NET 。固然如许既好用,而且也有充足的扩大性。之前用户须要革新页面或运用Ajax轮询才完成的及时显现数据,如今只需运用SignalR,就可以够简朴完成了。最主要的是您无需从新竖立项目,运用现有ASP .NET项目即可无缝运用SignalR。
群聊实例结果
咋们先来看看测试用例的结果吧,结果图:
界面及其简朴,款式这里就不斟酌了,主如果展现其用法,这里涉及到的功用有:
1. 统计在线人数目
2. 显如今线人数的昵称和衔接体式格局(本测试用例支撑webSockets和longPolling(长衔接))
3. 群聊信息
MVC中怎样运用SignalR
起首,我们寻常做法竖立MVC的Web项目,然后经由过程Nuget控制台敕令: Install-package Microsoft.AspNet.SignalR 到场SignalR的依靠,自动增添的包以下:
<package id="Microsoft.AspNet.SignalR" version="2.2.2" targetFramework="net45" /> <package id="Microsoft.AspNet.SignalR.Core" version="2.2.2" targetFramework="net45" /> <package id="Microsoft.AspNet.SignalR.JS" version="2.2.2" targetFramework="net45" /> <package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.2.2" targetFramework="net45" />
而且自动往MVC项目中的Script文件夹中增添相干的js文件:
jquery.signalR-2.2.2.min.js
jquery.signalR-2.2.2.js
然后,我们须要在项目一级目次竖立一个文件称号为Startup.cs的类,内里主要内容补全不下:
[assembly: OwinStartup(typeof(Stage.Api.Extend.Startup))] namespace Stage.Api.Extend { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR("/chat", new Microsoft.AspNet.SignalR.HubConfiguration { EnableDetailedErrors = true, EnableJavaScriptProxies = true }); } } }
起首我们从上往下剖析注重点:
1. OwinStartup(Type)
组织函数通报的是一个范例,而这个范例对应的就是我们竖立的Startup类,这个经由过程这个组织函数类标记肇端位置;
2. namespace Stage.Api.Extend
是我项目标定名空间,这个能够随意定义;
3. public void Configuration(IAppBuilder app)
函数是牢固必需的,这里顺序会起首进入这个要领实行内里的逻辑代码;
4. app.MapSignalR
是扩大的IAppBuilder接口要领,他有多种表现形式,这里我挑选的是 public static IAppBuilder MapSignalR(this IAppBuilder builder, string path, HubConfiguration configuration);
,这里看有点类似于咋们MVC的路由,这里主要注重的是这个Path参数,在前端页面的时刻须要用到这个途径;
到这里背景须要的设置实在已就完成了,下面是细致须要操纵的营业逻辑处置惩罚类,新建一个类(这里我取名为ChatHub)并继续Hub(这是SignalR框架供应),然后内里的逻辑代码以下:
public class ChatHub : Hub { // public int Num = 10001; public static List<MoHubUser> _Users = new List<MoHubUser>(); /// <summary> /// 增添谈天人 /// </summary> /// <param name="user"></param> public void AddUser(MoHubUser user) { user.Id = Context.ConnectionId; if (!_Users.Any(b => b.Id == user.Id)) { _Users.Add(user); } //Clients.All.newUser(user); Clients.All.userList(_Users); } /// <summary> /// 发送信息 /// </summary> /// <param name="user"></param> /// <param name="message"></param> public void SendAll(MoHubUser user, string message) { Clients.All.addNewMessageToPage(user, message); } /// <summary> /// 某个谈天人退出是,关照一切在线人从新加载谈天人数 /// </summary> /// <param name="stopCalled"></param> /// <returns></returns> public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) { var user = _Users.SingleOrDefault(x => x.Id == Context.ConnectionId); if (user != null) { _Users.Remove(user); Clients.All.userList(_Users); } return base.OnDisconnected(stopCalled); } }
上面的3个要领离别做了:增添谈天人到List,发送信息到客户端,某个衔接失效后关照各个有用的谈天人从新加载信息;这里值得关注的是经由过程从新 public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
要领来完成捕捉并移除失效衔接(这里是谈天人的信息);整篇测试用例经由过程Context.ConnectionId来保证衔接的唯一性,只需有新的链接请求,那末服务端就会分派一个唯一串给这个链接,当客户端封闭页面或封闭链接这个是有就可以在OnDisconnected要领中捕捉到这个失效的链接的ConnectionId,如许就达到了移除失效谈天人的请求了;为了代码的方便性,这里竖立了一个谈天人信息类:
public class MoHubUser { public string Id { get; set; } public string NickName { get; set; } public string TransportMethod { get; set; } }
到这里背景的谈天室代码就完成了就是这么简朴;我们再来看试图中怎样来写代码,这里我先给出我的html规划代码:
@{ ViewBag.Title = "神牛谈天室 - SignalR"; } <style type="text/css"> .p_left { width: 70%; float: left; } .p_right { width: 28%; float: left; } .ul { list-style: none; border: 1px solid #ccc; height: 500px; overflow-y: scroll; color: black; } .ul li { padding-top: 5px; padding-right: 25px; } .ul_user { list-style: none; } .ul_user li { padding-top: 5px; } .send { position: relative; background: #eae7e7; border-radius: 5px; /* 圆角 */ padding-top: 4px; padding-left: 5px; margin-top: 13px; } .send .arrow { position: absolute; top: -16px; font-size: 0; border: solid 8px; border-color: #fff #fff #eae7e7 #fff; } </style> <h3>@ViewBag.Title 在线人数:<span id="sapnUserTotal">0</span>人</h3> <p class="container text-left"> <p class="p_left"> <ul class="ul" id="discussion"></ul> <textarea rows="5" class="form-control" id="message" maxlength="500" placeholder="最先谈天. . ." style="max-width: 100%"></textarea><br /> <input type="button" id="sendmessage" value="发 送" class="btn btn-default" /> <input type="hidden" id="displayname" /> </p> <p class="p_right"> <ul id="users" class="ul_user"></ul> </p> </p> <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script> @*<script src="~/chat/hubs"></script>*@
客户端这里写法大抵有两种挑选,一种直接运用生成的代办来操纵,一种不必自动生成的代办采纳手动竖立代办的体式格局;为了内容的简洁性,这里只简朴解说下自动生成的代办体式格局,而更多的是分享手动竖立代办链接的体式格局;
运用生成的代办猎取链接
起首,我们须要经由过程Script标签来援用一下自动生成代办的途径: <script src="~/chat/hubs"></script>
,注重啦这里的途径/chat对应的就是咋们在前面Startup.cs文件中设置 app.MapSignalR("/chat"
途径,而背面/hubs牢固的写法(最少现在我还没更多的实验过),只要先应用了这个~/chat/hubs,才在背面运用生成的代办,先上段代码:
var chat = $.connection.chatHub; chat.client.newUser = function (user) { $("#users").append(' <li><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong></li>'); }; chat.client.userList = function (users) { console.log(users); $("#sapnUserTotal").html(users.length); $.each(users, function (i, item) { $("#users").append(' <li>[' + item.TransportMethod + '] <strong>' + item.NickName + '</strong>(' + item.Id + ')</li>'); }); }; chat.client.addNewMessageToPage = function (user, message) { console.log(user); $("#discussion").append(' <li ><span><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong>:</span><p class="send">' + message + '<p class="arrow"></p></p></li>'); }; //connection.hub.start({ transport: ['webSockets', 'longPolling'] }).done(function () { // my.TransportMethod = connection.hub.transport.name; // chat.server.addUser(my); // $('#sendmessage').click(function () { // //console.log(chat); // var content = $.trim($('#message').val()); // if (content.length <= 0) { $('#message').val('').focus(); return; } // chat.server.sendAll(my, content); // $('#message').val('').focus(); // }); //}).fail(function () { // alert("链接谈天室失利,请从新革新页面。"); //});
咋们逐步来剖析下代码注重点:
1. var chat = $.connection.chatHub;
这里的chatHub对应的就是咋们竖立的并继续Hub的ChatHub类,由于js变量开首都是小写,所以这里是chatHub,这句活就示意链接到咋们后端了ChatHub类了,然后就可以够运用内里的要领啦(这类有点类似于初期的webform中某种ajax请求的写法)
2. 经由过程chat.client.xxx来接收服务端关照的音讯,而这个xxx对应的要领称号和咋们后端的Clients.All.xxx,本章实例对应的是:chat.client.userList = function (users){}对应Clients.All.userList(_Users);如许后端就可以直接关照客户端的对应要领了;注重这里我后端Clients.All用的是关照悉数客户端的意义,如果您须要关照指定的链接须要用到的是: T Client(string connectionId);
要领
3. chat.client是后端挪用客户端,那相对的chat.server就是客户端请求服务端,和上面一样经由过程chat.server.xxx来指定请求的服务端要领,注重这个时刻服务端要领指的是继续类Hub的子类的大众要领(本篇对应的是:chat.server.sendAll(my, content)对应ChatHub.cs文件中的 public void SendAll(MoHubUser user, string message)
函数)
4. connection.hub.start({ transport: ['webSockets', 'longPolling'] })
来指定运转的交互协定
以上就是运用生成代办的体式格局,根据上面的注重点来写应当不是题目;
运用手动竖立反向代办来链接
不采纳生成的代码的体式格局,我们只须要修正前端就好了,背景代码不必变或设置不必更改;起首我们把上面说的Script援用自动代办的代码去掉,由于这个时刻不须要了,我们照样先上代码:
var my = { NickName: "神牛001", TransportMethod: "" }; var connection = $.hubConnection("/chat/hubs"); var chat = connection.createHubProxy('chatHub'); chat.on("userList", function (users) { console.log(users); $("#sapnUserTotal").html(users.length); $("#users").html(""); $.each(users, function (i, item) { $("#users").append(' <li>[' + item.TransportMethod + '] <strong>' + item.NickName + '</strong>(' + item.Id + ')</li>'); }); }); chat.on("addNewMessageToPage", function (user, message) { console.log(user); $("#discussion").append(' <li ><span><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong>:</span><p class="send">' + message + '<p class="arrow"></p></p></li>'); var p = document.getElementById('discussion'); //p.scrollTop = p.scrollHeight; p.scrollTop = 999999; }); var nickName = prompt("请输入一个昵称:", my.NickName); my.NickName = nickName.length > 0 ? nickName : my.NickName; $('#displayname').val(nickName); $('#message').focus(); connection.start({ transport: ['webSockets', 'longPolling'] }).done(function () { my.TransportMethod = connection.transport.name; //console.log(my.TransportMethod); chat.invoke("addUser", my); $('#sendmessage').click(function () { var content = $.trim($('#message').val()); if (content.length <= 0) { $('#message').val('').focus(); return; } chat.invoke("sendAll", my, content); $('#message').val('').focus(); }); });
一样列出以下注重点:
1. var connection = $.hubConnection("/chat/hubs");
竖立链接,这里的path一样对应后端的 app.MapSignalR("/chat" ,途径保持一致
2. var chat = connection.createHubProxy('chatHub');
来竖立反向代办链接,这里的name:chatHub对应的是后端的ChatHub类称号
3. 经由过程on("xxx",function(){})函数来绑定服务端关照客户端的事宜,xxx对应Clients.All.xxx中的xxx
4. connection.start({ transport: ['webSockets', 'longPolling'] })
来设置许可的链接体式格局,并最先链接
5. connection.transport.name来猎取链接的体式格局称号,默许start不设置的话有这么几种:webSockets,foreverFrame,serverSentEvents,longPolling
6. chat.invoke("xxx", param1, param2)经由过程invoke来映照继续类Hub的类的大众要领,这里实例对应的是: chat.invoke("sendAll", my, content)
对应 public void SendAll(MoHubUser user, string message)
以上就是SignalR完成及时Web谈天的实例代码的细致内容,更多请关注ki4网别的相干文章!