SignalR:建立连接时,是否可以强制连接在服务器端使用特定传输

本文关键字:连接 服务器端 传输 建立 是否 SignalR | 更新日期: 2023-09-27 18:34:34

在使用 SignalR 开发服务器客户端推送机制时,我遇到了最大并发连接问题。 即每个浏览器进程仅支持到同一域的大约 6 个并发连接。

我目前正在跟踪哪些用户与哪些连接相关联,并且在用户有三个打开的连接后,我想强制来自同一用户的其他连接对传输使用长轮询而不是 Web 套接字。通过这种方式,我希望完全避免连接耗尽的问题。

我总是可以在客户端上执行此操作,服务器提供非 SignalR 机制来通知客户端,如果他们的 Web 套接字连接用完,然后客户端可以在打开 SignalR 连接时指定长轮询,但这似乎效率低下。我真的很想在连接打开时将传输设置为适当的。

类似于集线器类中的以下内容。

    /// <summary>
    /// Chooses the correct transport depending on a users connections
    /// </summary>        
    public override Task OnConnected()
    {
        if(CanOpenWebSocketsConnection(Context.User.Identity.Name))
        {
            Connection.Transport = Connections.WebSockets;
        }
        else
        {
            Connection.Transport = Connections.LongPolling;
        }
        return base.OnConnected();                
    }

SignalR:建立连接时,是否可以强制连接在服务器端使用特定传输

与传统的 longPolling 和 iFrame 机制一样,SignalR 传输类型由客户端而不是服务器启动。SignalR 只是这些传输类型的包装器。此问题的解决方法是让服务器告诉客户端使用特定类型重新连接。

服务器代码:

[HubName("moveShape")]
public class MoveShapeHub : Hub
{
    public override Task OnConnected()
    {
        if (Context.QueryString["transport"] == "webSockets")
        {
            return Clients.Caller.changeTransport("longPolling");
        }
    }
}

客户端代码:

var hubConnection = new HubConnection("http://localhost:1235/");
var hub = hubConnection.CreateHubProxy("moveShape");
hub.On<string>("changeTransport", transportName =>
    Dispatcher.InvokeAsync(() =>
    {
        if (transportName == "longPolling")
        {
            hubConnection.Stop();
            hubConnection.Start(new LongPollingTransport());
        }
    }));
await hubConnection.Start();

我已经测试了这个解决方案。它在 SignalR v2.2 下工作。这是我的 Github 示例项目。(不知何故,在 SignalR v0.5.2 下,集线器连接在停止后不会重新启动(。