Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StreamingHub has already been disconnected from the server #777

Open
licentia88 opened this issue May 13, 2024 · 2 comments
Open

StreamingHub has already been disconnected from the server #777

licentia88 opened this issue May 13, 2024 · 2 comments

Comments

@licentia88
Copy link

Hello, I'm using magiconion hubs in my blazor project,
I have a hub implementation for a Ticket System, the goal is to perform crud operations on tickets and display the data for all company members. therefore my TicketHub is registered as a Singleton Service

I connect to the server on appstart and use the same service in the hub.

.My hub is derived from a base class that has the below methods, and use the below configuration
for simplicity sake I'm not sharing all the code, but in case anyone asks for it I can gladly share.

The Problem: after deploying the app in IIS and launch it after a while when I try to use the Hub Methods I get an exception telling me that StreamingHub has already been disconnected from the server.

I also want to mention that I do not manually disconnect /dispose the connection at anypoint.

My code declaration is below:

/// <summary>
/// Connects to the service hub.
/// </summary>
/// <returns>A task representing the async operation.</returns>
public virtual async Task<Guid> ConnectAsync()
{
    //AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

    string baseUrl = Configuration.GetValue<string>("API_BASE_URL:HTTPS");

    var SslAuthOptions = CreateSslClientAuthOptions();

    var socketHandler = CreateHttpClientWithSocketsHandler(SslAuthOptions, Timeout.InfiniteTimeSpan, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(30));

    var channelOptions = CreateGrpcChannelOptions(socketHandler);

    var channel = GrpcChannel.ForAddress(baseUrl, channelOptions);
  
    Client = await StreamingHubClient.ConnectAsync<THub, TReceiver>(
        channel, this as TReceiver, null, default, MemoryPackMagicOnionSerializerProvider.Instance);

    var connectionId = await Client.ConnectAsync();

    return connectionId;
}

/// <summary>
/// Creates SSL client authentication options for gRPC client communication.
/// </summary>
/// <param name="certificate">The X509 certificate used for client authentication.</param>
/// <returns>An instance of <see cref="SslClientAuthenticationOptions"/> configured with the certificate and validation callback.</returns>
public SslClientAuthenticationOptions CreateSslClientAuthOptions(X509Certificate2 certificate = default)
{
    return new SslClientAuthenticationOptions
    {
        RemoteCertificateValidationCallback = (sender, cert, _, _) =>
        {
            X509Chain x509Chain = new X509Chain();
            x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
            return certificate is null || x509Chain.Build(new X509Certificate2(cert));
            //bool isChainValid = x509Chain.Build(new X509Certificate2(cert));
            //return isChainValid;
        },
        //ClientCertificates = new X509Certificate2Collection { certificate }
    };
}

/// <summary>
/// Creates an instance of <see cref="SocketsHttpHandler"/> configured with provided options.
/// </summary>
/// <param name="sslClientAuthenticationOptions">The SSL client authentication options.</param>
/// <param name="pooledConnectionIdleTimeout">The timeout for idle pooled connections.</param>
/// <param name="keepAlivePingDelay">The delay between keep-alive pings.</param>
/// <param name="keepAlivePingTimeout">The timeout for keep-alive pings.</param>
/// <param name="enableMultipleHttp2Connections">Indicates whether multiple HTTP/2 connections are enabled.</param>
/// <returns>An instance of <see cref="SocketsHttpHandler"/> configured with the provided options.</returns>
public SocketsHttpHandler CreateHttpClientWithSocketsHandler(SslClientAuthenticationOptions sslClientAuthenticationOptions,
 TimeSpan pooledConnectionIdleTimeout,
 TimeSpan keepAlivePingDelay,
 TimeSpan keepAlivePingTimeout,
 bool enableMultipleHttp2Connections = true)
{
    var socketsHandler = new SocketsHttpHandler
    {
        SslOptions = sslClientAuthenticationOptions,
        PooledConnectionIdleTimeout = pooledConnectionIdleTimeout,
        KeepAlivePingDelay = keepAlivePingDelay,
        KeepAlivePingTimeout = keepAlivePingTimeout,
        EnableMultipleHttp2Connections = enableMultipleHttp2Connections
    };

    return socketsHandler;
}

/// <summary>
/// Creates gRPC channel options with the provided <see cref="SocketsHttpHandler"/>.
/// </summary>
/// <param name="socketsHandler">The configured <see cref="SocketsHttpHandler"/>.</param>
/// <returns>An instance of <see cref="GrpcChannelOptions"/> with the specified HTTP handler and message size limits.</returns>
public GrpcChannelOptions CreateGrpcChannelOptions(SocketsHttpHandler socketsHandler)
{
    var channelOptions = new GrpcChannelOptions
    {
        HttpHandler = socketsHandler,
        MaxReceiveMessageSize = null,
        MaxSendMessageSize = null
    };

    return channelOptions;
}
@Nektarinchik
Copy link

I have exactly the same problem only when app deployed on IIS.
Client tells, that server reset the stream, but server tells, that client has been disconnected.
@licentia88 may be you have any updates?

@licentia88
Copy link
Author

Hi, unfortunately, I couldn't fix the issue on the IIS side, but I came up with a workaround on the client side.

I created a method that runs every minute using a scheduler (similar to a ping).

You can check out a template project that shows how to implement MagicOnion and other Cysharp projects. If you look at MagicHubClientBase.cs in Client/Hubs/Base, you'll find the solution I came up with.

Here's the link to the repo:
https://github.com/licentia88/MagicOnionGenericTemplate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants