SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提高,5个Demo贯彻全篇,感兴趣的玩才是真的学)javascript
官方demo:http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalrcss
应用情景之一:前端
没太多连续的时间来研究SignalR,因此我把这篇文章分了三个阶段:java
第一个阶段,简单使用,熟悉并认识SignalRjquery
第二个阶段,实现上图的单聊效果web
第三个阶段,实现相似QQ群发的功能浏览器
扩展阶段,若是有时间,逆天会再开一篇,封装一个LoTSignalR,看过逆天封装的人都知道,绝对简单又轻量级服务器
好比LoTQQ,如今已经不少人在用了,后期会添加新功能,敬请期待~~架构
++++++++++++++++++ 我是华丽的分割线 +++++++++++++++++++++
步入正轨:
第一个阶段:
1.什么是ASP.NET SignalR?
ASP .NET SignalR是一个 ASP .NET 下的类库,能够在ASP .NET 的Web项目中实现实时通讯。什么是实时通讯的Web呢?就是让客户端(Web页面)和服务器端能够互相通知消息及调用方法,固然这是实时操做的。
WebSockets是Html5提供的新的API,能够在Web网页与服务器端间创建Socket链接,当WebSockets可用时(即浏览器支持Html5)SignalR使用WebSockets,当不支持时SignalR将使用其它技术来保证达到相同效果。
SignalR固然也提供了很是简单易用的高阶API,使服务器端能够单个或批量调用客户端上的JavaScript函数,而且很是 方便地进行链接管理,例如客户端链接到服务器端,或断开链接,客户端分组,以及客户端受权,使用SignalR都很是 容易实现。
2.可使用ASP.NET SingalR作什么?
SignalR 将与客户端进行实时通讯带给了ASP .NET 。固然这样既好用,并且也有足够的扩展性。之前用户须要刷新页面或使用Ajax轮询才能实现的实时显示数据,如今只要使用SignalR,就能够简单实现了。最重要的是您无需从新创建项目,使用现有ASP .NET项目便可无缝使用SignalR。
网上某架构图:
上面乱七八糟的估计不少人懒得看,好吧,你能够这样理解:
使用了SignalR就可让客户端经过SignalR代理直接调用服务端的方法,让服务端经过SignalR直接调用客户端的方法
下面咱们来实例演示一下,先演示一下不用IIS的状况:
新建一个控制台项目,引入 signalR Self Host (能够思考一下为何会用NuGet包,他到底好在哪?O(∩_∩)O~不清楚等项目演示完你应该就知道了)
这是他的依赖项
安装一下Owin.Cors
依赖项:
新增一个Owin的Startup类,相似于咱们传统项目的Global文件
注册一下signalR中间组件(学过mvc的能够变相的理解为注册路由之类的)
在main方法中绑定端口(不必定是8080,好比我demo中就用的其余端口)
建立一个“SignalR集线器”(控制台这边由于没有集线器因此只能本身建类)
建了一个DntHub,定义了一个服务器端的方法,叫ServiceSend(一会会用到)
转到定义,看看Hub类(好东西啊,还有分组啥的,下面会讲)
运行一下,若是出错请参考个人这篇文章:http://www.cnblogs.com/dunitian/p/5232229.html
先看看共引用多少dll(和MVC之类的比起是否是简洁不少?一会演示好处在哪)最小引用
建立一个web的Client,引用一下 SignalR的js包,其实你会发现就是多了几个js包并无引用任何dll(必须的,否则岂不是太臃肿?)
前端的调用步骤:
<!-- 总结一下: 1.先引入jq包,再引入signalR的js包,再引入signalR动态生成的hubs 2.设置signalR的hubs url地址:$.connection.hub.url =xxx 3.声明一个代理对象来引用集线器:var chat = $.connection.dntHub; 4.建立一个客户端方法:chat.client.xxxx=function(){} 5.启动并调用服务端方法: $.connection.hub.start().done(function(){ chat.server.xxx() }); -->代码贴起:
View Code<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>简单聊天程序</title> <style type="text/css"> .container { background-color: #99CCFF; border: thick solid #808080; padding: 20px; margin: 20px; } </style> </head> <body> <div class="container"> <input type="text" id="message" /> <input type="button" id="sendmessage" value="Send" /> <input type="hidden" id="displayname" /> <ul id="discussion"></ul> </div> <script src="Scripts/jquery-1.8.3.min.js"></script> <script src="Scripts/jquery.signalR-2.2.0.js"></script> <!--动态生成的--> <script src="http://localhost:5438/signalr/hubs"></script> <script type="text/javascript"> $(function () { //日记记录 $.connection.hub.logging = true; //设置hubs的url $.connection.hub.url = "http://localhost:5438/signalr"; // 声明一个代理来引用该集线器。 var chat = $.connection.dntHub; // 建立一个方法供服务端调用 chat.client.addMessage = function (name, message) { var encodedName = $('<div />').text(name).html(); var encodedMsg = $('<div />').text(message).html(); $('#discussion').append('<li><strong>' + encodedName + '</strong>: ' + encodedMsg + '</li>'); }; $('#displayname').val('路人'); // 启动 connection $.connection.hub.start().done(function () { $('#sendmessage').click(function () { //调用服务器端方法 chat.server.serviceSend($('#displayname').val(), $('#message').val()); }); }); }); </script> <!-- 总结一下: 1.先引入jq包,再引入signalR的js包,再引入signalR动态生成的hubs 2.设置signalR的hubs url地址:$.connection.hub.url =xxx 3.声明一个代理对象来引用集线器:var chat = $.connection.dntHub; 4.建立一个客户端方法:chat.client.xxxx=function(){} 5.启动并调用服务端方法: $.connection.hub.start().done(function(){ chat.server.xxx() }); --> </body> </html>若是要调试的话,保证服务端先运行,调试小技巧:
下面说一下上面的好处:
webclient我就单独拿出来了(一个js包,一个index.html),控制台的程序我也单独拿出来了,下面先运行一下服务端,再打开index.html
再次验证最上面说的,端口不固定
QQ聊天案例,先讲一种常规的方法,下面会讲一种简单方法
先看看gif效果图把
定义一个BaseHub类,里面用 qqModeList来临时存放数据(用户数据)
QQModel,目前就用到两个属性,其余的能够本身扩展
定义了一个上线方法,一会每一个客户端都会调用(原本是准备用OnConnected的,没办法他没参数。。。并且这个时候,qq昵称尚未产生,因而我取其次的方案)
定义一个发消息的方法
下面就是前端的东西了,注释很详细,不清楚能够直接留言,我没高兴深度封装,主要就是简单演示一下
代码贴上:
客户端-逆天
View Code<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>仿QQ聊天--我是逆天</title> <link href="Style/MyQQ.css" rel="stylesheet" /> </head> <body> <div><input id="inputMsg" /><input id="btn" type="button" value="发消息" /></div><br /><br /> <div id="main"></div> <script src="Scripts/jquery-2.2.1.min.js"></script> <script src="Scripts/jquery.signalR-2.2.0.min.js"></script> <script src="http://localhost:5438/signalr/hubs"></script> <script type="text/javascript"> $(function () { var leftHtml = [ '<div class="sender">', '<div><img src="http://img.jfdown.com/jfdown/201403/ygald3wajct.jpg"></div>', '<div><div class="left_triangle"></div>', '<span>{msg}</span></div></div>' ].join(''); var rightHtml = [ '<div class="receiver">', '<div><img src="http://tb.himg.baidu.com/sys/portrait/item/306c9328?t=1397975854"></div>', '<div><div class="right_triangle"></div>', '<span>{msg}</span></div></div>' ].join(''); //设置hubs的url $.connection.hub.url = 'http://localhost:5438/signalR'; // 声明一个代理 var qqProxy = $.connection.qQHub; // 建立一个方法供服务端调用 qqProxy.client.sendMsg = function (msg) { $('#main').append(leftHtml.replace('{msg}', msg)); } // 启动 connection $.connection.hub.start().done(function () { qqProxy.server.online('逆天');//QQ昵称 $('#btn').click(function () { //获取输入 var qqmsg = $('#inputMsg').val(); //给逆天发消息 qqProxy.server.serviceSend('妹子', qqmsg); $('#main').append(rightHtml.replace('{msg}', qqmsg)); }); }); }); </script> </body> </html>客户端-美女
View Code<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>仿QQ聊天--我是美女</title> <link href="Style/MyQQ.css" rel="stylesheet" /> </head> <body> <div><input id="inputMsg" /><input id="btn" type="button" value="发消息" /></div><br /><br /> <div id="main"></div> <script src="Scripts/jquery-2.2.1.min.js"></script> <script src="Scripts/jquery.signalR-2.2.0.min.js"></script> <script src="http://localhost:5438/signalr/hubs"></script> <script type="text/javascript"> $(function () { var rightHtml = [ '<div class="sender">', '<div><img src="http://img.jfdown.com/jfdown/201403/ygald3wajct.jpg"></div>', '<div><div class="left_triangle"></div>', '<span>{msg}</span></div></div>' ].join(''); var leftHtml = [ '<div class="receiver">', '<div><img src="http://tb.himg.baidu.com/sys/portrait/item/306c9328?t=1397975854"></div>', '<div><div class="right_triangle"></div>', '<span>{msg}</span></div></div>' ].join(''); //设置hubs的url $.connection.hub.url = 'http://localhost:5438/signalR'; // 声明一个代理 var qqProxy = $.connection.qQHub; // 建立一个方法供服务端调用 qqProxy.client.sendMsg = function (msg) { $('#main').append(leftHtml.replace('{msg}', msg)); } // 启动 connection $.connection.hub.start().done(function () { qqProxy.server.online('妹子');//QQ昵称 $('#btn').click(function () { //获取输入 var qqmsg = $('#inputMsg').val(); //给逆天发消息 qqProxy.server.serviceSend('逆天', qqmsg); $('#main').append(rightHtml.replace('{msg}', qqmsg)); }); }); }); </script> </body> </html>
群发
咱们先接着昨天的QQ聊天来讲
此次用一个简单的方法搞定
一个键值对集合存放ConnectionId和GroupName
每一个客户端链接的时候会加入一个组
断开的时候退出组
发消息![]()
前端也进行了优化。ok,signalR第三个demo诞生,比昨天简单多了
这个是逆天的自学笔记: