I’ve started playing with gRPC
, having 3 projects:
- WPF as a Client,
- Class Library as a business logic,
- GRPC Server as a Windows Service.
This is what I see often:
Status(StatusCode=”Unavailable”, Detail=”Error starting gRPC call.
HttpRequestException: No connection could be made because the target
machine actively refused it. (localhost:80) SocketException: No
connection could be made because the target machine actively refused
it.”, DebugException=”System.Net.Http.HttpRequestException: No
connection could be made because the target machine actively refused
it. (localhost:80)”)
This error is welcoming me more often during the debugging.
I’m using Unix Domain Sockets
as a communication protocol.
My Program.cs
is configured in that way:
var builder = WebApplication.CreateBuilder(args);
var socketPath = Path.Combine(@"C:Temp", "app-socket.socket");
builder.Services.AddSingleton<Settings>();
builder.Services.AddGrpc();
builder.Services.AddSingleton<ISettingsService>(provider => provider.GetRequiredService<Settings>());
builder.Services.AddSingleton<IConnectionService>(provider =>
{
var settings = provider.GetRequiredService<Settings>();
return new ConnectionService(settings.GetAServerAddress(), Settings.GetBServerAddress());
});
builder.Services.AddSingleton<IPackageService>(provider => { return new PackageService(provider.GetRequiredService<Settings>()); });
builder.WebHost.ConfigureKestrel(serverOptions =>
{
if (File.Exists(socketPath))
{
File.Delete(socketPath);
}
serverOptions.ListenUnixSocket(socketPath, listenOptions =>
{
listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2;
});
});
builder.Host.UseWindowsService();
builder.Services.AddGrpcReflection();
var app = builder.Build();
app.MapGrpcService<GrpcSettingsService>();
app.MapGrpcService<GrpcConnectionService>();
app.MapGrpcService<GrpcPackageService>();
app.MapGrpcReflectionService();
Console.WriteLine($"gRPCServer is running and listening on {socketPath}");
app.Run();
On the Client I have something like:
public partial class MainWindow : Window
{
private readonly GrpcChannel _channel;
private readonly GrpcSettings.GrpcSettingsClient _grpcSettingsClient;
public MainWindow()
{
Task.Delay(5000);
InitializeComponent();
var socketPath = Path.Combine(@"C:Temp", "app-socket.socket");
_channel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
{
HttpHandler = CreateHttpHandler(socketPath)
});
_grpcSettingsClient = new GrpcSettings.GrpcSettingsClient(_channel);
DataContext = new MainViewModel(_grpcSettingsClient);
}
private static HttpMessageHandler CreateHttpHandler(string socketPath)
{
var udsEndPoint = new UnixDomainSocketEndPoint(socketPath);
return new SocketsHttpHandler
{
ConnectCallback = async (context, cancellationToken) =>
{
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
await socket.ConnectAsync(udsEndPoint, cancellationToken);
return new NetworkStream(socket, ownsSocket: true);
}
};
}
}
The Task.Delay(5000)
was added to be sure that the Server will start before GUI, when I combined “Multiple Statup Options”.
I was trying multiple things, but when I play with it more and more it starts to occurs more often.
I’m wondering what is happening, because I’m not using any ports, but all things are done through socket…
In the production GRPC Server will run as a Windows Service as different User & GUI will be run as a local one.