Compartilhar via


Comunicação entre processos com o gRPC e pipes nomeados

Por James Newton-King

O .NET dá suporte à IPC (comunicação entre processos) usando gRPC. Para saber mais sobre como começar a usar o gRPC para se comunicar entre processos, confira Comunicação entre processos com gRPC.

Pipes nomeados são um transporte IPC com suporte em todas as versões do Windows. Os pipes nomeados integram-se bem à segurança do Windows para controlar o acesso do cliente ao pipe. Este artigo discute como configurar a comunicação gRPC em pipes nomeados.

Pré-requisitos

  • .NET 8 ou posterior
  • Windows

Configuração de Servidor

Os pipes nomeados são compatíveis com Kestrel, que é configurado em Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenNamedPipe("MyPipeName", listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http2;
    });
});

No exemplo anterior:

Configuração do cliente

GrpcChannel dá suporte à realização de chamadas gRPC em transportes personalizados. Quando um canal é criado, ele pode ser configurado com um SocketsHttpHandler que tem um ConnectCallback personalizado. O retorno de chamada permite que o cliente faça conexões por meio de transportes personalizados e envie solicitações HTTP por esse transporte.

Observação

Alguns recursos de conectividade de GrpcChannel, como o balanceamento de carga do lado do cliente e o status do canal, não podem ser usados junto aos pipes nomeados.

Exemplo de fábrica de conexões de pipes nomeados:

public class NamedPipesConnectionFactory
{
    private readonly string pipeName;

    public NamedPipesConnectionFactory(string pipeName)
    {
        this.pipeName = pipeName;
    }

    public async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext _,
        CancellationToken cancellationToken = default)
    {
        var clientStream = new NamedPipeClientStream(
            serverName: ".",
            pipeName: this.pipeName,
            direction: PipeDirection.InOut,
            options: PipeOptions.WriteThrough | PipeOptions.Asynchronous,
            impersonationLevel: TokenImpersonationLevel.Anonymous);

        try
        {
            await clientStream.ConnectAsync(cancellationToken).ConfigureAwait(false);
            return clientStream;
        }
        catch
        {
            clientStream.Dispose();
            throw;
        }
    }
}

Usando a fábrica de conexões personalizadas para criar um canal:

public static GrpcChannel CreateChannel()
{
    var connectionFactory = new NamedPipesConnectionFactory("MyPipeName");
    var socketsHttpHandler = new SocketsHttpHandler
    {
        ConnectCallback = connectionFactory.ConnectAsync
    };

    return GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
    {
        HttpHandler = socketsHttpHandler
    });
}

Os canais criados usando o código anterior enviam chamadas gRPC por pipes nomeados.