简体   繁体   中英

Storing the connection id of a specific client in SignalR hub

Below you can see a simplified version of my SignalR self hosted hub on a windows service:

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);
    }
}

And I have two types of clients for that hub: One of them is web applications and the other one is windows services. Here you can see a demo implementation for my windows service as a signalr client:

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()
    {
    }
}

As you see I use the hasSubscribers flag to minimize the messages between hub and clients. And hasSubscribers flag is changed by SubscribeToPriceFeed and UnsubscribeFromPriceFeed methods.

If you look carefully you see the line below in SubscribeToPriceFeed:

context.Clients.All.updatePriceSubscriptionStatus(true);

I don't want to send the message to all clients but my client windows service. How can I store the connection Id of a specific client in my hub? If I can do that, I know I can send message to a specific connectionId as in the line below:

context.Clients.Client(connectionId).updatePriceSubscriptionStatus(true);

Thanks in advance,

pass source during connection

like this

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

HUB

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

create a class which will hold the user with source

public class user {
  public string ConnectionID {set;get;}
  public string Source {set;get;}
}

declare a list in the hub

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

Then push the user during OnConnected

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

and during broadcast just filter it by source

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM