【问题标题】:How can I send SignalR message to a single client?如何向单个客户端发送 SignalR 消息?
【发布时间】:2021-11-05 22:32:39
【问题描述】:

对于我的生活,我无法弄清楚如何将 SignalR 消息仅发送给点击“开始”按钮的客户端,而没有其他人。当我将它发送到“All”时一切正常,但我不知道如何在服务器上获取 connectionID,然后将消息发送到启动客户端。这就是我迄今为止的工作。如果您能告诉我如何仅使用调用客户端来完成这项工作,我将不胜感激 -

这是我的 Default.aspx 文件

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SignalR5._Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">

    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <div><br /><br />
                <asp:Button ID="btnGo" runat="server" Text="GO!!!" OnClick="btnGo_Click" OnClientClick="this.disabled=true;" UseSubmitBehavior="false" /><br /><br />
                <asp:Label ID="lblLog" class="#log" runat="server" Text="Begin"></asp:Label> <br /> <br />
                <asp:Label ID="lblConnectionID" runat="server" Text=""></asp:Label>
            </div>
        </ContentTemplate>
    </asp:UpdatePanel>

    <script src="Scripts/jquery-3.4.1.js"></script>
    <script src="Scripts/jquery.signalR-2.4.2.js"></script>
    <script src="signalr/hubs"></script>

    <script type="text/javascript">
        $(function() {   

            var logger = $.connection.logHub;

            logger.client.logMessage = function(msg) {

                $("#MainContent_lblLog").html(msg);
            };

            $.connection.hub.start().done(function () {
                var cid = $.connection.hub.id;
                $("#MainContent_lblConnectionID").text("ConnectionID: " + cid);
                //alert("connection Id:" + cid);
            });
        });

    </script>
</asp:Content>

这是我的 Default.aspx.cs 文件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
using System.Diagnostics;

namespace SignalR5
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnGo_Click(object sender, EventArgs e)
        {
            //The timer is just to display how long each task takes.
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            
            string strMessage = "Hello ";
            LogHub.SendMessage(strMessage);
            Thread.Sleep(2000);
            strMessage += "(" + stopWatch.Elapsed.Seconds + " Seconds)<br>what's up bro? ";

            stopWatch.Restart();
            LogHub.SendMessage(strMessage);
            Thread.Sleep(2500);
            strMessage += "(" + stopWatch.Elapsed.Seconds + " Seconds)<br>Call me soon ";

            stopWatch.Restart();
            LogHub.SendMessage(strMessage);
            Thread.Sleep(3200);
            strMessage += "(" + stopWatch.Elapsed.Seconds + " Seconds)<br>See you later ";

            stopWatch.Restart();
            LogHub.SendMessage(strMessage);
            Thread.Sleep(1800);
            strMessage += "(" + stopWatch.Elapsed.Seconds + " Seconds)<br>Okay man. See you ";

            stopWatch.Restart();
            LogHub.SendMessage(strMessage);
            Thread.Sleep(2900);
            strMessage += "(" + stopWatch.Elapsed.Seconds + " Seconds)<br>We're all Done!";
            lblLog.Text = strMessage;
            
            stopWatch.Stop();
        }
    }
}

这是我的 Startup1.cs 文件

using Microsoft.Owin;
using Owin;
using System;
using System.Threading.Tasks;

[assembly: OwinStartup(typeof(SignalR5.Startup1))]

namespace SignalR5
{
    public class Startup1
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

这是我的 LogHub.cs 文件

using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SignalR5
{
    public class LogHub : Hub
    {
        // This is the only one working, but I don't want to send to all clients. 
        public static void SendMessage(string strMessage)
        {
            var hub = GlobalHost.ConnectionManager.GetHubContext("LogHub");
            hub.Clients.All.logMessage(strMessage);
   
        }
    }
}

正如我所提到的,我很难弄清楚如何将其发送给“调用者”客户端。它适用于“所有”。

【问题讨论】:

  • 尝试发送连接 ID (here you will get an idea about connection id),然后使用该连接 ID 而不是这样做 -hub.Clients.All.logMessage(strMessage); ,发送此 hub.Clients.Client(yourConnectionId).logMessage(strMessage);
  • 向我们展示您接受连接并将其与用户关联的代码部分
  • @TBA,老实说,我不知道如何在服务器端获取 connectionid。我可以在客户端得到它。我花了好几天才写出上面的代码。无论如何,您可以给我更多详细信息或告诉我我需要在上面修改什么以获得 connectionId?
  • @CaiusJard,不幸的是,以上就是我所拥有的。我已经尝试了几天,无法弄清楚如何将其发送给调用客户端。
  • 这是一个新项目还是对现有项目的改造?

标签: c# asp.net signalr


【解决方案1】:

当调用你的“Go”按钮时,你应该调用服务器中的“Go”方法,然后你就可以将数据发送到Caller,比如:

await hub.Clients.Caller.logMessage(message);

【讨论】:

  • 感谢您,但我绝对不是 SignalR 或 C# 专家,我无法让您的建议发挥作用。有什么办法可以给我更多细节或告诉我上面代码的哪一部分我需要修改?调用者似乎不是 hub.Clients 的一部分。
【解决方案2】:

连接到 SignalR 集线器的每个客户端都有一个唯一的连接 ID。我们可以使用集线器上下文的 Context.ConnectionId 属性来检索它。使用它,我们可以只向那个特定的客户端发送消息。 Learn more about this here.

因此,要向特定客户端发送消息,您将需要他们的连接 ID 来识别您要将消息发送到哪个客户端。

我在这里做了一个演示,用于向特定用户发送消息。这是集线器类。这个 send 方法会像往常一样向所有连接的客户端发送消息,但我做的额外的事情是,在开始时注册他们的连接 ID 和用户名,以便我以后可以访问它们。

public static class UserHandler
    {
        // just remember when you will restart the app, object will get reset
        public static HashSet<string> ConnectedIds = new HashSet<string>();
        public static HashSet<string> ConnectedUsers = new HashSet<string>();
    }

 public void Send(string name, string message)
        {
            // registering the users
            UserHandler.ConnectedIds.Add(Context.ConnectionId);
            UserHandler.ConnectedUsers.Add(name);

            // Call the broadcastMessage method to update clients.
            Clients.All.broadcastMessage(name, message);
        }

这个SendToSingleUser 方法用于向特定用户发送消息,至于虚拟目的,我只是从列表中随机抽取第一个客户端。如果您已经知道要将它发送给哪个用户,那么您可以将 id 传递给方法并在连接列表中查找 Id 以确保它是有效的连接。

public void SendToSingleUser(string userName, string message)
        {

            string fromUserId = Context.ConnectionId;
            //removing the currrent user ID & name
            UserHandler.ConnectedIds.Remove(fromUserId);
            UserHandler.ConnectedUsers.Remove(userName);

            //taking a random user for sending message
            string toUserId = UserHandler.ConnectedIds.First();
            string toUserName = UserHandler.ConnectedUsers.First();

            if (toUserId != null && fromUserId != null)
            {
                // send to 
                Clients.Client(toUserId).sendPrivateMessage(userName, message);

                // send to caller user
                Clients.Caller.sendPrivateMessage(userName, message);
            }

        } 

aspx 文件:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Chat.aspx.cs" Inherits="SignalRChat.Chat" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>SignalR Chat : Chat Page</title>

    <link href="Content/bootstrap.css" rel="stylesheet" />
    <link href="Content/style.css" rel="stylesheet" />
    <link href="Content/font-awesome.css" rel="stylesheet" />

    <script src="Scripts/jQuery-1.9.1.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.2.min.js"></script>
    <script src="Scripts/date.format.js"></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="signalr/hubs"></script>


    <script type="text/javascript">

        $(function () {

            // Declare a proxy to reference the hub. 
            var chat = $.connection.chatHub;
            // Create a function that the hub can call to broadcast messages.
            chat.client.broadcastMessage = function (name, message) {
                // Html encode display name and message. 
                var encodedName = $('<div />').text(name).html();
                var encodedMsg = $('<div />').text(message).html();
                // Add the message to the page. 
                $('#discussion').append('<li><strong>' + encodedName
                    + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
            };

            // Create a function that the hub can call to broadcast private messages
            chat.client.sendPrivateMessage = function (name, message) {
                // Html encode display name and message. 
                var encodedName = $('<div />').text(name).html();
                var encodedMsg = $('<div />').text(message).html();
                // Add the message to the page. 
                $('#discussion').append('<li><strong>' + encodedName
                    + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
            };


            // Get the user name and store it to prepend to messages.
            $('#displayname').val(prompt('Enter your name:', ''));
            $('#CurrentUser').append($('#displayname').val());
            // Set initial focus to message input box.  
            $('#message').focus();
            // Start the connection.
            $.connection.hub.start().done(function () {

                //send to all user
                $('#sendmessage').click(function () {

                    var msg = $("#message").val();

                    if (msg.length > 0) {
                        debugger;
                        var userName = $('#displayname').val();
                        chat.server.send(userName, msg);
                        $('#message').val('').focus();
                    }
                });

                //send to a sepcific user
                $('#sendToSingleUser').click(function () {

                    var msg = $("#message").val();

                    if (msg.length > 0) {
                        debugger;
                        var userName = $('#displayname').val();
                        chat.server.sendToSingleUser(userName, msg);
                        $('#message').val('').focus();
                    }
                });
            });
        });

    </script>

</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server" ></asp:ScriptManager>
        <div class="content-wrapper">
            <div class="row">
                 <div class="container">
                    <label id="CurrentUser"> </label>
                    <input type="text" id="message" />
                    <input type="button" id="sendmessage" value="Send" />
                    <input type="button" id="sendToSingleUser" value="Send Single User" />
                    <input type="hidden" id="displayname" />
                    <ul id="discussion">
                    </ul>
                </div>
            </div>
        </div>

         <script src="Scripts/bootstrap.min.js"></script>

    </form>
</body>
</html>

完整的演示可以在here找到

注意:此演示与您发布的示例不同,我只是想告诉您如何实现通信。

【讨论】:

    猜你喜欢
    • 2013-04-16
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 1970-01-01
    • 2015-03-03
    相关资源
    最近更新 更多