zoukankan      html  css  js  c++  java
  • ASP.NET SignalR 系列(四)之指定对象推送

    在上一章讲到了广播推送,即所有订阅的用户都能收到,这种适合于信息广播。

    接下来介绍如何给指定的对象推送

    在讲这个之前先说明一下连接创建的基础知识

    1、每个页面与服务端创建连接并启动时,这时服务端会产生一个connectionId作为与这个客户端连接的唯一标识。

    2、这个connectionId将作为服务端向指定客户端推送的依据

    3、同一个页面刷新后ConnectionId一样不变

    4、这个connectionId是服务端自动生成的一个随机数,无法变更。

    一、只推送给自己

    为了与之前的例子区分,我们分别在服务端DemoHub新建个发送给自己的方法

    public class DemoHub : Hub
        {
            /// <summary>
            /// 示例
            /// </summary>
            /// <param name="content">广播的内容</param>
            public void Hello(string content)
            {
                Clients.All.show(content); //调用了前端js上定义的hello方法
            }
    
            /// <summary>
            /// 推送给自己
            /// </summary>
            /// <param name="content"></param>
            public void CallSelf(string content)
            {
                Clients.Caller.show(content);
            }
        }

    这里使用了Caller,而不是All,表示只推送给呼叫方,即自己。

    前端脚本逻辑不变,只是多了一个发送给自己的按钮的推送到服务端CallSelf事件而已。

          //定义推送
            $.connection.hub.start()
                .done(function () {
                    $("#btn_sendCall").click(function () {
                        chat.server.callSelf($("#content").val());  //将客户端的content内容发送到服务端
                        $("#content").val("");
                    });
                });

    结果:



    我是在窗口2这边发送的,第一条点击“发送”按钮,是广播,两个窗口都能收到;第二条点击“发送给自己”,只有窗口2收到。

    二、其他推送方式

    其他推送方式对于客户端(前端)来说不变,主要就是服务端推送对象改变而已

    以下列出其他推送方式:

    • 所有连接的客户端  
      Clients.All.show(content);

    • 仅调用的客户端
      Clients.Caller.show(content);

    • 除调用客户端之外的所有客户端
      Clients.Others.show(content);

    • 特定的客户端标识的连接 id
      Clients.Client(Context.ConnectionId).show(content);

    • 所有连接的客户端除外指定客户端,由连接 ID 标识
      Clients.AllExcept(connectionId1, connectionId2).show(content);

    • 指定组中的所有连接的客户端
      Clients.Group(groupName).show(content);
    • 指定组中的所有连接的客户端除外指定客户端,由连接 ID 标识。
      Clients.Group(groupName, connectionId1, connectionId2).show(content);

    • 所有连接的客户端指定组中除调用客户端
      Clients.OthersInGroup(groupName).show(content);

    • 所有客户端和组列表中的连接 Id
      Clients.Clients(ConnectionIds).show(content);

    • 组的列表。
      Clients.Groups(GroupIds).show(content);

    • 按名称的用户
      Clients.Client(username).show(content);  //这里的username我还没理解是怎么创建的

    • (在 SignalR 2.1 中引入) 的用户名称的列表。
      Clients.Users(new string[] { "myUser", "myUser2" }).show(content)

    三、说说ConnectionId

    前面已经说到,每个连接的页面都会产生不同的连接id,并且这个连接id是随机产生,不能自定义的,那我们如何获取呢

    集线器中为我们提供了Context对象可以获取到这个连接id,先看下面简单的例子

         /// <summary>
            /// 返回每个连接的id
            /// </summary>
            public void ReturnConnectionId()
            {
                Clients.Caller.show(Context.ConnectionId);
            }

    前端:

         //定义推送,返回各个客户端连接
            $.connection.hub.start()
                .done(function () {
                    $("#btn_sendConnectionId").click(function () {
                        chat.server.returnConnectionId();  //将客户端的content内容发送到服务端
                    });
                });

    结果:

     从结果可以看出,分别点击返回各自的id,返回了不同的id。这个就验证了系统给每个调用端分配一个不相同的随机ConnectionId。

    那我们如何利用这个ConnnectionId来实现给某个客户端发送消息,比如一对一的聊天。这个就需要我们实现将人与ConnectionId信息建立对应关系。

    如,我们假设张三和李四一对一聊天,那怎么实现,张三发送李四的消息只有李四收到呢,反之,亦然。即我们需要分别确定张三和李四的ConnectionId,并将它们的ConnnectionId与张三、李四建立对应关系。

    即建立以下的对应关系
    张三   张三的ConnectionId
    李四   李四的ConnectionId

    张三和李四是已知的,那么就需要在张三和李四分别与集线器建立连接生成ConnenctionId时,我们就要实现对应关系的建立。

    这时候需要重载建立连接的方法:

    服务端:

         /// <summary>
            /// 发送给指定连接
            /// </summary>
            /// <param name="toName"></param>
            /// <param name="content"></param>
            public void CallOne(string toName,string content)
            {
                //根据username获取对应的ConnectionId
                var connectionId = HttpContext.Current.Application[toName].ToString();
                Clients.Client(connectionId).show(content);
            }
    
            /// <summary>
            /// 初次连接
            /// </summary>
            /// <returns></returns>
            public override Task OnConnected()
            {
                string username = Context.QueryString["userName"]; //获取客户端发送过来的用户名
                string connectionId = Context.ConnectionId;
                HttpContext.Current.Application.Add(username,connectionId); //存储关系
                return base.OnConnected();
            }

    客户端:建立zhangsan.html和lisi.html 分别表示张三和李四的窗口

    zhangsan.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title></title>
        <link href="Content/bootstrap.min.css" rel="stylesheet" />
        <script src="Scripts/jquery-1.10.2.min.js"></script>
        <script src="Scripts/jquery.signalR-2.3.0.min.js"></script>
        <script src="/signalr/hub/hubs"></script>
        <meta charset="utf-8"/>
        <style type="text/css">
            body {
                margin: 20px;
            }
            .input {
                padding-left: 5px;
            }
    
        </style>
    </head>
    <body>
    <div>
        <h4>我是张三</h4>
        <p>
            <input type="text" id="content" placeholder="" class="input"/> &nbsp;&nbsp;<input type="button" value="发送给李四" class="btn btn-sm btn-info" id="btn_send"/>
        </p>
    
        <div>
            <h4>接收到的信息:</h4>
            <ul id="dataContainer">
    
            </ul>
        </div>
    </div>
    
    <script language="javascript">
        $(function() {
            var chat = $.connection.demoHub; //连接服务端集线器,demoHub为服务端集线器名称,js上首字母须改为小写(系统默认)
            //定义客户端方法,此客户端方法必须与服务端集线器中的方法名称、参数均一致。
            //实际上是服务端调用了前端的js方法(订阅)
    
            $.connection.hub.qs = { 'userName': '张三' }
            chat.client.show=function(content) {
                var html = '<li>' + htmlEncode(content) + "</li>";
                $("#dataContainer").append(html);
            }
    
            //定义推送
            $.connection.hub.start()
                .done(function() {
                    $("#btn_send").click(function() {
                        chat.server.callOne("李四",$("#content").val());  //将客户端的content内容发送到服务端
                        $("#content").val("");
                    });
                });
        });
        //编码
        function htmlEncode(value) {
            var encodedValue = $('<div />').text(value).html();
            return encodedValue;
        }
    </script>
    </body>
    </html>

    lisi.html:

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        <link href="Content/bootstrap.min.css" rel="stylesheet" />
        <script src="Scripts/jquery-1.10.2.min.js"></script>
        <script src="Scripts/jquery.signalR-2.3.0.min.js"></script>
        <script src="/signalr/hub/hubs"></script>
        <meta charset="utf-8" />
        <style type="text/css">
            body {
                margin: 20px;
            }
    
            .input {
                padding-left: 5px;
            }
        </style>
    </head>
    <body>
        <div>
            <h4>我是李四</h4>
            <p>
                <input type="text" id="content" placeholder="" class="input" /> &nbsp;&nbsp;<input type="button" value="发送给张三" class="btn btn-sm btn-info" id="btn_send" />
            </p>
    
            <div>
                <h4>接收到的信息:</h4>
                <ul id="dataContainer"></ul>
            </div>
        </div>
    
        <script language="javascript">
        $(function() {
            var chat = $.connection.demoHub; //连接服务端集线器,demoHub为服务端集线器名称,js上首字母须改为小写(系统默认)
            //定义客户端方法,此客户端方法必须与服务端集线器中的方法名称、参数均一致。
            //实际上是服务端调用了前端的js方法(订阅)
            $.connection.hub.qs = { 'userName': '李四' }
            chat.client.show=function(content) {
                var html = '<li>' + htmlEncode(content) + "</li>";
                $("#dataContainer").append(html);
            }
    
            //定义推送
            $.connection.hub.start()
                .done(function() {
                    $("#btn_send").click(function() {
                        chat.server.callOne("张三", $("#content").val());  //将客户端的content内容发送到服务端
                        $("#content").val("");
                    });
                });
        });
        //编码
        function htmlEncode(value) {
            var encodedValue = $('<div />').text(value).html();
            return encodedValue;
        }
        </script>
    </body>
    </html>

    说明:

    1、参数传递的方法

     $.connection.hub.qs = { 'userName': '李四' }

    2、后端获取参数的方法:

    Context.QueryString["username"]

    3、本例中利用Application对象来存储用户与ConnectionId的对应关系,当然,实际项目中也可以用其他方式存储。

    示例结果:

    本章结束!

  • 相关阅读:
    Oracle日期函数大全
    Android Permission(授权)大全
    澳大利亚项目VBA部分简略代码
    Android模拟器安装程序及上传音乐并播放
    更改电脑背景颜色,保护您的眼睛
    编写高效Excel VBA代码的最佳实践(一)
    VBA复制粘贴效率问题
    编写高效Excel VBA代码的最佳实践(二)
    编写高效Excel VBA代码的最佳实践(二)
    Android新浪星座运势程序开发
  • 原文地址:https://www.cnblogs.com/fei686868/p/9562468.html
Copyright © 2011-2022 走看看