web服务端向客户发送提示信息

加密整理信息:
之前有一个网站需要向客户发送某些信息。构建了一点思路。


1、可以使用ajax定时请求:
让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。
或者:long poll 其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始
这种有点像下面这种场景
客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request)
服务端:额。。 等待到有消息的时候。。来 给你(Response)
客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop
从上面可以看出其实这两种方式,都是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协议的另外一个特点,被动性。
何为被动性呢,其实就是,服务端不能主动联系客户端,只能有客户端发起。
简单地说就是,服务器是一个很懒的冰箱(这是个梗)(不会、不能主动发起连接),但是上司有命令,如果有客户来,不管多么累都要好好接待。
说完这个,我们再来说一说上面的缺陷(原谅我废话这么多吧OAQ)
从上面很容易看出来,不管怎么样,上面这两种都是非常消耗资源的。
ajax轮询 需要服务器有很快的处理速度和资源。(速度)long poll 需要有很高的并发,也就是说同时接待客户的能力。(场地大小)
所以 ajax轮询 和 long poll 都有可能发生这种情况。
客户端:啦啦啦啦,有新信息么?
服务端:月线正忙,请稍后再试(503 Server Unavailable)
客户端:。。。。好吧,啦啦啦,有新信息么?
服务端:月线正忙,请稍后再试(503 Server Unavailable)
客户端:然后服务端在一旁忙的要死:冰箱,我要更多的冰箱!更多。。更多。。(我错了。。这又是梗。。)
2、下面就到WebSockets了
先简单介绍下WebSockets:
通过上面这个例子,我们可以看出,这两种方式都不是最好的方式,需要很多资源。
一种需要更快的速度,一种需要更多的’电话’。这两种都会导致’电话’的需求越来越高。
哦对了,忘记说了HTTP还是一个状态协议。
通俗的说就是,服务器因为每天要接待太多客户了,是个健忘鬼,你一挂电话,他就把你的东西全忘光了,把你的东西全丢掉了。你第二次还得再告诉服务器一遍。
所以在这种情况下出现了,Websocket出现了。他解决了HTTP的这几个难题。首先,被动性,当服务器完成协议升级后(HTTP->Websocket),服务端就可以主动推送信息给客户端啦。所以上面的情景可以做如下修改。
客户端:啦啦啦,我要建立Websocket协议,需要的服务:chat,Websocket协议版本:17(HTTP Request)
服务端:ok,确认,已升级为Websocket协议(HTTP Protocols Switched)
客户端:麻烦你有信息的时候推送给我噢。。
服务端:ok,有的时候会告诉你的。
服务端:balabalabalabala
服务端:balabalabalabala
服务端:哈哈哈哈哈啊哈哈哈哈
服务端:笑死我了哈哈哈哈哈哈哈
就变成了这样,只需要经过一次HTTP请求,就可以做到源源不断的信息传送了。(在程序设计中,这种设计叫做回调,即:你有信息了再来通知我,而不是我傻乎乎的每次跑来问你 )
这样的协议解决了上面同步有延迟,而且还非常消耗资源的这种情况。那么为什么他会解决服务器上消耗资源的问题呢?
其实我们所用的程序是要经过两层代理的,即HTTP协议在Nginx等服务器的解析下,然后再传送给相应的Handler(PHP等)来处理。简单地说,我们有一个非常快速的 接线员(Nginx) ,他负责把问题转交给相应的 客服(Handler) 。
本身接线员基本上速度是足够的,但是每次都卡在客服(Handler)了,老有客服处理速度太慢。,导致客服不够。Websocket就解决了这样一个难题,建立后,可以直接跟接线员建立持久连接,有信息的时候客服想办法通知接线员,然后接线员在统一转交给客户。
这样就可以解决客服处理速度过慢的问题了。
同时,在传统的方式上,要不断的建立,关闭HTTP协议,由于HTTP是非状态性的,每次都要重新传输 identity info (鉴别信息),来告诉服务端你是谁。
虽然接线员很快速,但是每次都要听这么一堆,效率也会有所下降的,同时还得不断把这些信息转交给客服,不但浪费客服的处理时间,而且还会在网路传输中消耗过多的流量/时间。
但是Websocket只需要一次HTTP握手,所以说整个通讯过程是建立在一次连接/状态中,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请求,这样就解决了接线员要反复解析HTTP协议,还要查看identity info的信息。
同时由客户主动询问,转换为服务器(推送)有信息的时候就发送(当然客户端还是等主动发送信息过来的。。),没有信息的时候就交给接线员(Nginx),不需要占用本身速度就慢的客服(Handler)了
3、好了现在实现一下(下面借鉴一下别人的demo,就不重写了哈)

ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信。什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消息及调用方法,当然这是实时操作的。
WebSockets是 HTML5提供的新的API,可以在Web网页与服务器端间建立Socket连接,当WebSockets可用时(即浏览器支持Html5)SignalR使用WebSockets,当不支持时SignalR将使用其它技术来保证达到相同效果。
SignalR当然也提供了非常简单易用的高阶API,使服务器端可以单个或批量调用客户端上的JavaScript函数,并且非常 方便地进行连接管理,例如客户端连接到服务器端,或断开连接,客户端分组,以及客户端授权,使用SignalR都非常 容易实现。

一、首先,在MVC项目中安装SingalR包(SingalR2.0需要.net4.5以上,VS2010可以安装1.1.3版本,本例为VS2010+SignalR1.1.3)。

web服务端向客户发送提示信息_第1张图片

打开工具—NuGet程序管理器—程序包管理器控制台,输入:

Install-Package Microsoft.AspNet.SignalR-Version 1.1.3

web服务端向客户发送提示信息_第2张图片

安装完成后,一定要阅读弹出的txt,这里非常重要,

web服务端向客户发送提示信息_第3张图片

有两个很重要的提示,一是在Global.asax文件中加入RouteTable.Routes.MapHubs();二是在页面前端加入脚本(注:本示例采用的是MVC4MVC其他版本有其他的写法,所以要读这个readme)。

二、安装完signalr包后,我们在项目中添加一个Home控制器以及它的ViewView选择母版页,记得在这个页面里加上

<script src="../../Scripts/jQuery.signalR-1.1.4.min.js"type="text/JavaScript">script>

然后在项目中创建一个目录,目录里创建Hub类文件:

public class WorkflowHubHub

    {

        /// 

        /// 静态用户列表

        /// 

        private IList<string> userList = UserInfo.userList;

 

        /// 

        /// 用户的connectionID与用户名对照表

        /// 

        private readonly static Dictionary<stringstring>_connections = new Dictionary<stringstring>();

 

       /// 

       /// 发送函数,前端触发该函数给服务器,服务器在将消息发送给前端,(Clients.All.(函数名)是全体广播,另外Clients提供了组播,广播排除,组播排除,指定用户播发等等)

       /// 该函数名在前端使用时一定要注意,前端调用该函数时,函数首字母一定要小写

       /// 

       /// 发起者

       /// 消息接收者

        public voidSendByGroup(string name1, string name2)

        {

            //Client内为用户的id,是唯一的,SendMessage函数是前端函数,意思是服务器将该消息推送至前端

           Clients.Client(_connections[name2]).SendMessage("来自用户"+name1 + " " + DateTime.Now.ToString("yyyy/MM/ddhh:mm:ss")+"的消息推送!");

        }

 

        /// 

        /// 用户上线函数

        /// 

        /// 

        public voidSendLogin(string name)

        {

            if (!userList.Contains(name))

            {

               userList.Add(name);

               //这里便是将用户id和姓名联系起来

               _connections.Add(name, Context.ConnectionId); 

            }

            else

            {

               //每次登陆id会发生变化

               _connections[name] = Context.ConnectionId;

            }

            //新用户上线,服务器广播该用户名

           Clients.All.loginUser(userList);

        }

}

其中

public class UserInfo

    {

        public static IList<string>userList = new List<string>();

    }

为用户名称列表

 web服务端向客户发送提示信息_第4张图片

HomeView中,Index.cshtml

<script src="../../Scripts/jquery.signalR-1.1.4.min.js"type="text/javascript">script>

    

    <script src="~/signalr/hubs">script>

<h1>流程演示h1>

<input type="hidden" id="displayname" />

<h2 id="thisname">h2><br />

 

<select id="username" style="width:153px;">

select>

<input id="send" type="button" value="发送" />

<div>

<h1 id="messgae">h1>

div>

<script type="text/javascript">

    $(function () {

 

       //前端Hub的使用,注意的是,Hub的名字是WorkflowHub,这里使用时首字母小写

        var work = $.connection.workflowHub;

 

        $('#displayname').val(prompt('请输入昵称:'''));

        $('#thisname').text('当前用户:'+$('#displayname').val());

 

        //对应后端的SendMessage函数,消息接收函数

       work.client.sendMessage = function(message) {

            $('#messgae').append(message + '
'
)

        };

 

        //后端SendLogin调用后,产生的loginUser回调

       work.client.loginUser = function(userlist) {

           reloadUser(userlist);

        };

 

        //hub连接开启

        $.connection.hub.start().done(function () {

 

            var username = $('#displayname').val();

 

            //发送上线信息

           work.server.sendLogin(username);

 

            //点击按钮,发送消息

            $('#send').click(function() {

               var friend = $('#username').val();

               //调用后端函数,发送指定消息

               work.server.sendByGroup(username, friend);

            });

 

        });

    });

 

    //重新加载用户列表

    var reloadUser = function(userlist) {

        $("#username").empty();

        for (i = 0;i < userlist.length; i++) {

            $("#username").append("+userlist[i]+"");

        }

    }

script>

调试执行,打开两个网页(如果提示signalr必须在jquery之后,就在_layout.cshtml中把jquery放前面),输入用户名称,登录后在列表中会显示当前登录的用户的信息:

web服务端向客户发送提示信息_第5张图片

另一个网页中输入李晨:

web服务端向客户发送提示信息_第6张图片

我们在李晨这里,给邓超发送,这样我们就会在邓超这里看到推送的消息了:

web服务端向客户发送提示信息_第7张图片

新增

SignalR跨域访问基于MVC4.5,SignalR2.2
客户端配置成服务端的地址:
   
 
    
    
    
    
    
                    
                    

你可能感兴趣的:(.net)