在SignalR集线器中存储特定客户端的连接id

本文关键字:客户端 连接 id SignalR 集线器 存储 | 更新日期: 2023-09-27 18:13:41

下面你可以看到我在windows服务上的SignalR自托管中心的简化版本:

public static class SubscriptionHandler
{
    public static int PriceFeedMembersCount = 0;
}
public class PriceHub : Hub
{
    public Task SubscribeToPriceFeed()
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
        if (SubscriptionHandler.PriceFeedMembersCount == 0)
        {
            context.Clients.All.updatePriceSubscriptionStatus(true);
        }
        SubscriptionHandler.PriceFeedMembersCount++;
        return context.Groups.Add(Context.ConnectionId, "PriceFeed");
    }
    public Task UnsubscribeFromPriceFeed()
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
        SubscriptionHandler.PriceFeedMembersCount--;
        if (SubscriptionHandler.PriceFeedMembersCount == 0)
        {
            context.Clients.All.updatePriceSubscriptionStatus(false);
        }
        return context.Groups.Remove(Context.ConnectionId, "PriceFeed");
    }
    public void NotifySubscribers(Price price)
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
        context.Clients.Group("PriceFeed").updatePrice(price);
    }
}

对于这个集线器我有两种类型的客户端:一种是web应用程序,另一种是windows服务。这里你可以看到我的windows服务作为信号客户端的演示实现:

public partial class WinSer45 : ServiceBase
{
    private HubConnection hubConnection;
    private IHubProxy priceProxy;
    private Timer timer = new Timer();
    private bool hasSubscribers = false;
    public WinSer45()
    {
        InitializeComponent();
    }
    protected override void OnStart(string[] args)
    {
        timer.Interval = 1000; // saniyede bir
        timer.Elapsed += timer_Elapsed;
        timer.Enabled = true;
        hubConnection = new HubConnection("http://localhost:8080/signalr", useDefaultUrl: false);
        priceProxy = hubConnection.CreateHubProxy("PriceHub");
        hubConnection.Start().Wait();
        priceProxy.On<bool>("UpdatePriceSubscriptionStatus", hasSubscribers =>
        {
            this.hasSubscribers = hasSubscribers;
        });
    }
    void timer_Elapsed(object sender, ElapsedEventArgs e)
    {   
        if (hasSubscribers)
        {
            TestPrice testPrice = new TestPrice() { Id = 1, Buy = 1.2345, Sell = 9.8765, Symbol = "EURUSD" };
            priceProxy.Invoke("NotifySubscribers", testPrice).Wait();    
        }
    }   
    protected override void OnStop()
    {
    }
}
如您所见,我使用hasSubscribers标志来最小化集线器和客户机之间的消息。hasSubscribers标志被SubscribeToPriceFeedUnsubscribeFromPriceFeed方法改变。

如果仔细看,可以看到SubscribeToPriceFeed:

中的下面一行

context.Clients.All.updatePriceSubscriptionStatus(真正);

我不想发送消息给所有客户端,但我的客户端windows服务。如何在集线器中存储特定客户机的连接Id ?如果我能做到这一点,我知道我可以发送消息到一个特定的connectionId,如下行所示:

context.Clients.Client (connectionId) .updatePriceSubscriptionStatus(真正);

提前致谢

在SignalR集线器中存储特定客户端的连接id

在连接时传递源

这样的

hubConnection = new HubConnection("http://localhost:8080/signalr","source=windows",useDefaultUrl: false);

public override Task OnConnected()
{
    var source= Context.QueryString['source'];
    return base.OnConnected();
}

创建一个类,它将保存源

的用户
public class user {
  public string ConnectionID {set;get;}
  public string Source {set;get;}
}

在hub中声明一个列表

List<user> userList=new List<user>();

然后在OnConnected期间推送用户

public override Task OnConnected()
{
    var us=new user();
    us.Source = Context.QueryString['source'];
    us.ConnectionID=Context.ConnectionId;
    userList.Add(us);
    return base.OnConnected();
}

并且在广播期间仅通过源

进行过滤
var windowsUser=userList.Where(o=>o.Source == "windows").ToList(); // you'll get the windows user list