最近比较累,也没时间写博客,今天索性来一篇,很多时候,网站即时通讯,推送必不可少。但是这部分大家都觉得是那么陌生,不敢尝试,今天我就给大家讲讲SignalR的简单使用。
首先我们打开VS,创建一个web应用程序。然后Nuget安装SignalR,如下。
安装好之后,我们在项目的引用中发现程序给我们自动引用了相关的dll以及js文件。
接着我们创建两个类,一个是ChatHub,继承自Hub,如下
using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Web; namespace Chart.SignalR { [HubName("ChatRoomHub")] public class ChatHub : Hub { static List<UserEntity> users = new List<UserEntity>(); public async Task UserEnter(string nickName) { UserEntity userEntity = new UserEntity { NickName = nickName, ConnectionId = Context.ConnectionId }; users.Add(userEntity); await Clients.All.NotifyUserEnter(nickName, users); } public async Task SendMessage(string nickName, string message) { await Clients.All.NotifySendMessage(nickName, message); } public override Task OnDisconnected(bool isStop) { var currentUser = users.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId); if (currentUser != null) { users.Remove(currentUser); Clients.Others.NotifyUserLeft(currentUser.NickName, users); } return base.OnDisconnected(isStop); } } public class UserEntity { public string NickName { get; set; } public string ConnectionId { get; set; } } }
在这里我们给ChatHub起了别名ChatRoomHub。大家从代码上看就知道我写的将是一个聊天室的代码。这里users用来存储在线人员,NickName存放用户进聊天室之前输入的昵称,ConnectionId则是Hub上下文给每个连接分配的唯一标识,这样方便我们判断用户离线的情况。
在这个Hub子类中,
UserEnter方法用来记录加入聊天的用户,并通知到其他客户端浏览器更新UI。
SendMessage方法用来将客户端发送的消息推送到所有的客户端浏览器。
OnDisconnected顾名思义就是客户端离线,离线后将离线用户从用户数组中删除掉,并通知其他用户浏览器更新UI,注意这里的Clients.Others
接着我们再看一下StartUp类
using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Chart.SignalR.StartUp))] namespace Chart.SignalR { public class StartUp { public void Configuration(IAppBuilder app) { app.MapSignalR(); } } }
这里OwinStartup标识了哪个类是自动启动,app.MapSignalR()则是将app builder 管道映射到一个路径上,待会我们会看到这个路径。
OK,接下来我们看下客户端的代码
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <link rel="stylesheet" href="StyleSheet/bootstrap/css/bootstrap.min.css" /> <script src="Scripts/jquery-1.6.4.min.js"></script> <script src="Scripts/jquery.signalR-2.2.0.min.js"></script> <script src="Scripts/bootstrap.min.js"></script> <script src="signalr/hubs"></script> <style type="text/css"> .demo { margin-bottom: 20px; padding-left: 50px; position: relative; } .triangle { position: absolute; top: 50%; margin-top: -8px; left: 42px; display: inline; width: 0; height: 0; overflow: hidden; line-height: 0; font-size: 0; border-bottom: 8px solid #FFF; border-top: 8px solid #FFF; border-left: none; border-right: 8px solid #3079ED; } .demo .article { float: left; color: #FFF; display: inline; zoom: 1; padding: 5px 10px; border: 1px solid #3079ED; background: #eee; border-radius: 5px; background-color: #4D90FE; background-image: -webkit-gradient(linear,left top,left bottom,from(#4D90FE),to(#4787ED)); background-image: -webkit-linear-gradient(top,#4D90FE,#4787ED); background-image: -moz-linear-gradient(center top, #4D90FE, #4787ED); background-image: linear-gradient(top,#4D90FE,#4787ED); } .fr { padding-left: 0px; padding-right: 50px; } .fr .triangle { left: auto; right: 42px; border-bottom: 8px solid #FFF; border-top: 8px solid #FFF; border-right: none; border-left: 8px solid #3079ED; } .fr .article { float: right; } .round-img-list { border-radius: 50%; border: solid; border-width: 1px; border-color: #FFCC00; width: 45px; height: 45px; } .clear-float { clear: both; } </style> </head> <body> <div class="container" style="margin-top: 10px"> <div class="row"> <div class="col-md-9"> <div class="panel panel-primary"> <div class="panel-heading"> 聊天室 </div> <div id="div_msgbody" class="panel-body" style=‘min-height: 500px; max-height: 500px; overflow: auto; max-width: 850px;‘> <div id="div_msg" style=‘word-wrap: break-word; word-break: break-word;‘></div> </div> <div class="panel-footer"> <div class="row"> <div class="col-md-11"> <div class="input-group"> <span class="input-group-addon">内容:</span> <input id="message" type="text" class="form-control" maxlength="500" placeholder=‘在此输入聊天内容‘ /> </div> </div> <div class="col-md-1"> <button id="btn_Send" type="button" class="btn btn-info">发送</button> </div> </div> </div> </div> </div> <div class="col-md-3"> <div class="panel panel-primary"> <div class="panel-heading"> 用户列表 </div> <div class="panel-body" style=‘min-height: 500px; max-height: 500px; overflow: auto;‘> <div id="div_member"></div> </div> <div class="panel-footer"> <div style="height: 34px; height: 34px; line-height: 34px"> 人员总数:<label id="lab_total">0</label> </div> </div> </div> </div> </div> </div> <script type="text/javascript"> var userNickName; jQuery(document).ready(function () { while (!userNickName) { userNickName = window.prompt("请输入昵称!"); } var chatHub = $.connection.ChatRoomHub; chatHub.client.NotifyUserEnter = function (nickName, users) { buildUserTemplate(users); } chatHub.client.NotifyUserLeft = function (nickName, users) { buildUserTemplate(users); } chatHub.client.NotifySendMessage = function (nickName, message) { var userAvatar = ‘http://www.wed114.cn/jiehun/uploads/allimg/160426/39_160426110624_1.jpg‘; if (nickName == userNickName) { $("#div_msg").append("<div style=‘text-align:right;float:right‘>" + "<span style=‘margin-right:10px‘>" + nickName + "</span>" + "<img src=‘" + userAvatar + "‘ style=‘height:40px;width:40px;position:relative‘/>" + "<div class=‘demo clearfix fr‘>" + "<span class=‘triangle‘></span>" + "<div class=‘article‘ style=‘word‘>" + message + "</div></div></div><div class=‘clear-float‘/>"); } else { $("#div_msg").append("<div>" + "<img src=‘" + userAvatar + "‘ style=‘height:40px;width:40px;position:relative‘/>" + "<span style=‘left:10px;position:relative‘>" + nickName + "</span>" + "<div class=‘demo clearfix‘>" + "<span class=‘triangle‘></span>" + "<div class=‘article‘>" + message + "</div></div></div>"); } var objDiv = document.getElementById("div_msgbody"); objDiv.scrollTop = objDiv.scrollHeight; } $.connection.hub.start().done(function () { chatHub.server.userEnter(userNickName); }); $("#message").keydown(function (event) { if (event.keyCode == 13) { if ($("#message").val() != "") { chatHub.server.sendMessage(userNickName, $("#message").val()); $("#message").val(""); } } }); $("#btn_Send").click(function () { if ($("#message").text != "") { chatHub.server.sendMessage(userNickName, $("#message").val()); $("#message").val(""); } }) function buildUserTemplate(users) { $("#lab_total").text(users.length); var userTemplate = "<ul style=‘list-style:none;‘>" $.each(users, function (e, v) { var userAvatar = ‘http://www.wed114.cn/jiehun/uploads/allimg/160426/39_160426110624_1.jpg‘; userTemplate += "<li style=‘padding-top:5px;‘>" + "<img class=‘round-img-list‘ src=‘" + userAvatar + "‘/>" + "<label style=‘color:#666666;margin-left:10px‘>" + v.NickName + "</label>" + "</li>"; }); userTemplate += "</ul>"; $("#div_member").html(userTemplate); } }); </script> </body> </html>
布局我就不说了,BootStrap布局。这里需要注意这个路径
<script src="signalr/hubs"></script>
这个路径就是上面说的管道map的路径,在这个路径下会生成hubs.js文件,在这个文件中有注册hub代码,生成hub代理等方法。
然后在js中,先让用户输入昵称,输入后,得到chatHub对象,然后
实现NotifyUserEnter,NotifyUserLeft以及NotifySendMessage方法。NotifyUserEnter和NotifyUserLeft方法主要是更新右边panel显示的人员信息。而NotifySendMessage方法则是将服务器推送出的聊天信息展示在span中。在这里我们为了区分自己和别人,自己的聊天信息显示在右边,别人的显示在左边。
var objDiv = document.getElementById("div_msgbody"); objDiv.scrollTop = objDiv.scrollHeight;
这句的意思是如果聊天记录太多出现了滚动条,则将滚动条自动滚动到最底部。
$.connection.hub.start().done(function () { chatHub.server.userEnter(userNickName); });
这句意思是当有新用户时,就会和服务端建立连接,连接完成后,调用Server端的UserEnter方法,在客户端这里写小写开头,记住。最后发送消息,调用server端的SendMessage方法。
OK,至此程序大概就讲完了,很简单的一个demo,大家看了的也评价评价。俗话说无图无真相,看图
好了今天就到这里,后面我会继续写nodejs相关的博客。