다음을 통해 공유


gRPC 및 명명된 파이프와의 프로세스 간 통신

작성자: James Newton-King

.NET은 gRPC를 사용하는 IPC(프로세스 간 통신)를 지원합니다. gRPC를 사용하여 프로세스 간 통신을 시작하는 방법에 대한 자세한 내용은 gRPC와의 프로세스 간 통신을 참조하세요.

명명된 파이프 는 모든 버전의 Windows에서 지원되는 IPC 전송입니다. 명명된 파이프는 Windows 보안 과 잘 통합되어 파이프에 대한 클라이언트 액세스를 제어합니다. 이 문서에서는 명명된 파이프를 통해 gRPC 통신을 구성하는 방법을 설명합니다.

필수 조건

  • .NET 8 이상
  • 윈도우즈

서버 구성

명명된 파이프는 다음에서 구성된 다음에서 Kestrel지원Program.cs됩니다.

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

위의 예제는 다음과 같습니다.

  • Kestrel에서 ConfigureKestrel의 엔드포인트를 구성합니다.
  • 지정된 이름의 명명된 파이프를 수신 대기하기 위한 호출 ListenNamedPipe 입니다.
  • HTTPS를 사용하도록 구성되지 않은 명명된 파이프 엔드포인트를 만듭니다. HTTPS를 사용하도록 설정하는 방법에 대한 자세한 내용은 Kestrel HTTPS 엔드포인트 구성을 참조하세요.

명명된 파이프에 대한 PipeSecurity 구성

연결할 수 있는 사용자 또는 그룹을 제어하려면 클래스를 NamedPipeTransportOptions 사용합니다. 이렇게 하면 사용자 지정 PipeSecurity 개체를 지정할 수 있습니다.

예제:

using Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes;
using System.IO.Pipes;
using System.Security.AccessControl;

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

        // Configure PipeSecurity
        listenOptions.UseNamedPipes(options =>
        {
            var pipeSecurity = new PipeSecurity();
            // Grant read/write access to the Users group
            pipeSecurity.AddAccessRule(new PipeAccessRule(
                "Users",
                PipeAccessRights.ReadWrite,
                AccessControlType.Allow));
            // Add additional rules as needed

            options.PipeSecurity = pipeSecurity;
        });
    });
});

위의 예제는 다음과 같습니다.

  • 에 액세스하고 구성하는 UseNamedPipes데 사용합니다NamedPipeTransportOptions.
  • 명명된 파이프에 PipeSecurity 연결할 수 있는 사용자 또는 그룹을 제어할 속성을 설정합니다.
  • 그룹에 대한 읽기/쓰기 권한을 부여합니다 Users . 시나리오에 필요한 경우 추가 보안 규칙을 추가할 수 있습니다.

Kestrel 명명된 파이프 엔드포인트를 사용자 지정합니다

Kestrel'의 명명된 파이프 지원을 사용하면 고급 사용자 지정할 수 있으므로 옵션을 사용하여 CreateNamedPipeServerStream 각 엔드포인트에 대해 서로 다른 보안 설정을 구성할 수 있습니다. 이 방법은 여러 명명된 파이프 엔드포인트에 고유한 액세스 제어가 필요한 시나리오에 적합합니다. 엔드포인트당 파이프를 사용자 지정하는 기능은 .NET 9부터 사용할 수 있습니다.

이것이 유용한 예는 Kestrel 액세스 보안이 다른 두 개의 파이프 엔드포인트가 필요한 앱입니다. 이 CreateNamedPipeServerStream 옵션은 파이프 이름에 따라 사용자 지정 보안 설정을 사용하여 파이프를 만드는 데 사용할 수 있습니다.


var builder = WebApplication.CreateBuilder();
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenNamedPipe("pipe1");
    options.ListenNamedPipe("pipe2");
});

builder.WebHost.UseNamedPipes(options =>
{
    options.CreateNamedPipeServerStream = (context) =>
    {
        var pipeSecurity = CreatePipeSecurity(context.NamedPipeEndpoint.PipeName);

        return NamedPipeServerStreamAcl.Create(context.NamedPipeEndpoint.PipeName, PipeDirection.InOut,
            NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte,
            context.PipeOptions, inBufferSize: 0, outBufferSize: 0, pipeSecurity);
    };
});

클라이언트 구성

GrpcChannel은 사용자 지정 전송을 통한 gRPC 호출을 지원합니다. 채널을 만들 때 사용자 지정 SocketsHttpHandler가 포함된 ConnectCallback로 구성할 수 있습니다. 콜백을 사용하면 클라이언트가 사용자 지정 전송을 통해 연결한 다음 해당 전송을 통해 HTTP 요청을 보낼 수 있습니다.

비고

클라이언트 쪽 부하 분산 및 채널 상태와 같은 일부 연결 기능은 GrpcChannel명명된 파이프와 함께 사용할 수 없습니다.

명명된 파이프 연결 팩터리 예제:

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

사용자 지정 연결 팩터리를 사용하여 채널을 만듭니다.

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

이전 코드를 사용하여 만든 채널은 명명된 파이프를 통해 gRPC 호출을 보냅니다.