Freigeben über


Prozessübergreifende Kommunikation mit gRPC und Named Pipes

Von James Newton-King

.NET unterstützt die prozessübergreifende Kommunikation (Inter-Process Communication, IPC) mithilfe von gRPC. Weitere Informationen zu den ersten Schritten mit der Verwendung von gRPC für die Kommunikation zwischen Prozessen finden Sie unter Inter-Process Communication mit gRPC.

Named Pipes sind ein IPC-Transport, der in allen Versionen von Windows unterstützt wird. Named Pipes sind gut in die Windows-Sicherheit integriert, um den Clientzugriff auf die Pipe zu steuern. In diesem Artikel wird erläutert, wie Sie die gRPC-Kommunikation über Named Pipes konfigurieren.

Voraussetzungen

  • .NET 8 oder höher
  • Windows

Serverkonfiguration

Named Pipes werden von Kestrel unterstützt. Die Konfiguration erfolgt in Program.cs:

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

Für das vorherige Beispiel gilt Folgendes:

  • Der Endpunkt von Kestrel wird in ConfigureKestrel konfiguriert.
  • Ruft ListenNamedPipe auf, um auf eine Named Pipe mit dem angegebenen Namen zu lauschen.
  • Erstellt einen Named Pipe-Endpunkt, der nicht für die Verwendung von HTTPS konfiguriert ist. Informationen zum Aktivieren von HTTPS finden Sie unter Kestrel-HTTPS-Endpunktkonfiguration.

Clientkonfiguration

GrpcChannel unterstützt gRPC-Aufrufe für benutzerdefinierte Datentransporte. Wenn ein Kanal erstellt wird, kann er mit einer SocketsHttpHandler-Klasse konfiguriert werden, die über ein benutzerdefiniertes ConnectCallback-Objekt verfügt. Der Rückruf ermöglicht es dem Client, Verbindungen für benutzerdefinierte Datentransporte herzustellen und dann HTTP-Anforderungen über diese Datentransporte zu senden.

Hinweis

Einige Konnektivitätsfeatures von GrpcChannel, wie clientseitiger Lastenausgleich und Kanalstatus, können nicht zusammen mit Named Pipes verwendet werden.

Beispiel für eine Named Pipes-Verbindungsfactory:

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

So wird die benutzerdefinierte Verbindungsfactory zum Erstellen eines Kanals verwendet:

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

Kanäle, die mithilfe des vorangehenden Codes erstellt werden, senden gRPC-Aufrufe über Named Pipes.