본문 바로가기
C#

[C#] NamedPipeServerStream, NamedPipeClientStream

by DANEW 2023. 12. 4.

 

NamedPipeServerStream

 

NamedPipeServerStream Class (System.IO.Pipes)

Exposes a Stream around a named pipe, supporting both synchronous and asynchronous read and write operations.

learn.microsoft.com

namespace System.IO.Pipes
{
    public sealed class NamedPipeServerStream : PipeStream
    {
        public const int MaxAllowedServerInstances = -1;

        public NamedPipeServerStream(string pipeName);
        public NamedPipeServerStream(string pipeName, PipeDirection direction);
        public NamedPipeServerStream(string pipeName, PipeDirection direction, int maxNumberOfServerInstances);
        public NamedPipeServerStream(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode);
        public NamedPipeServerStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle);
        public NamedPipeServerStream(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options);
        public NamedPipeServerStream(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize);
        public NamedPipeServerStream(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity);
        public NamedPipeServerStream(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity, HandleInheritability inheritability);
        public NamedPipeServerStream(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity, HandleInheritability inheritability, PipeAccessRights additionalAccessRights);
        ~NamedPipeServerStream();

        public string GetImpersonationUserName();
        public void RunAsClient(PipeStreamImpersonationWorker impersonationWorker);

        public void WaitForConnection();
        public Task WaitForConnectionAsync(CancellationToken cancellationToken);
        public Task WaitForConnectionAsync();
        public IAsyncResult BeginWaitForConnection(AsyncCallback callback, object state);
        public void EndWaitForConnection(IAsyncResult asyncResult);
        
        public void Disconnect();
    }
}

 

NamedPipeClientStream

 

NamedPipeClientStream 클래스 (System.IO.Pipes)

동기 및 비동기 읽기/쓰기 작업을 모두 지원하는 명명된 파이프 주위의 Stream을 노출합니다.

learn.microsoft.com

namespace System.IO.Pipes
{
    public sealed class NamedPipeClientStream : PipeStream
    {
        public NamedPipeClientStream(string pipeName);
        public NamedPipeClientStream(string serverName, string pipeName);
        public NamedPipeClientStream(string serverName, string pipeName, PipeDirection direction);
        public NamedPipeClientStream(string serverName, string pipeName, PipeDirection direction, PipeOptions options);
        public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle);
        public NamedPipeClientStream(string serverName, string pipeName, PipeDirection direction, PipeOptions options, TokenImpersonationLevel impersonationLevel);
        public NamedPipeClientStream(string serverName, string pipeName, PipeDirection direction, PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability);
        public NamedPipeClientStream(string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability);

        ~NamedPipeClientStream();

        public int NumberOfServerInstances { get; }

        public void Connect();
        public void Connect(int timeout);
        public Task ConnectAsync();
        public Task ConnectAsync(int timeout);
        public Task ConnectAsync(CancellationToken cancellationToken);
        public Task ConnectAsync(int timeout, CancellationToken cancellationToken);
        
        protected internal override void CheckPipePropertyOperations();
    }
}

- 같은 이름의 파이프 하나를 이용해서 통신
 1. 서버가 NamedPipeServerStream 인스턴스를 생성하여 WaitForConnection을 호출
 2. 클라이언트가 NamedPipeClientStream 인스턴스를 생성하여 Connect를 호출
 3. 스트림 인스턴스를 읽고 쓰기

 

PipeDirection 열거형

 

NamedPipeServerStream Class (System.IO.Pipes)

Exposes a Stream around a named pipe, supporting both synchronous and asynchronous read and write operations.

learn.microsoft.com

namespace System.IO.Pipes
{
    public enum PipeDirection
    {
        In = 1,
        Out = 2,
        InOut = 3
    }
}

- 파이프의 방향 지정

반응형

PipeTransmissionMode 열거형

 

PipeTransmissionMode Enum (System.IO.Pipes)

Specifies the transmission mode of the pipe.

learn.microsoft.com

namespace System.IO.Pipes
{
    public enum PipeTransmissionMode
    {
        Byte = 0,
        Message = 1
    }
}

- 일반적인 바이트 모드로 보낼것인지, 혹은 메시지 전송 모드로 보낼 것인지
- 전송 모드를 켤 경우 IsMessageComplete로 메시지를 완전히 읽었는지 판단

PipeOptions 열거형

 

PipeOptions Enum (System.IO.Pipes)

Provides options for creating a PipeStream object. This enumeration has a FlagsAttribute attribute that allows a bitwise combination of its member values.

learn.microsoft.com

PipeSecurity 클래스

 

PipeSecurity Class (System.IO.Pipes)

Represents the access control and audit security for a pipe.

learn.microsoft.com

namespace System.IO.Pipes
{
    public class PipeSecurity : NativeObjectSecurity
    {
        public PipeSecurity();
        
        public override Type AccessRightType { get; }
        public override Type AccessRuleType { get; }
        public override Type AuditRuleType { get; }
        
        public override AccessRule AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type);
        public void AddAccessRule(PipeAccessRule rule);
        public void SetAccessRule(PipeAccessRule rule);
        public bool RemoveAccessRule(PipeAccessRule rule);
        public void RemoveAccessRuleSpecific(PipeAccessRule rule);
        public void ResetAccessRule(PipeAccessRule rule);

        public sealed override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags);
        public void AddAuditRule(PipeAuditRule rule);
        public void SetAuditRule(PipeAuditRule rule);
        public bool RemoveAuditRule(PipeAuditRule rule);
        public void RemoveAuditRuleSpecific(PipeAuditRule rule);
        public void RemoveAuditRuleAll(PipeAuditRule rule);

        protected internal void Persist(SafeHandle handle);
        protected internal void Persist(string name);
    }
}

- FileSecurity와 마찬가지로 파이프에 대한 보안 관련인듯? Access Rule과 Audit Rule 설정

HandleInheritability 열거형

 

HandleInheritability Enum (System.IO)

Specifies whether the underlying handle is inheritable by child processes.

learn.microsoft.com

- 자식 프로세스에게 파이프의 핸들을 상속할지 여부 설정

PipeAccessRights 열거형

 

PipeAccessRights Enum (System.IO.Pipes)

Defines the access rights to use when you create access and audit rules.

learn.microsoft.com

namespace System.IO.Pipes
{
    public enum PipeAccessRights
    {
        ReadData = 1,
        WriteData = 2,
        CreateNewInstance = 4,
        ReadExtendedAttributes = 8,
        WriteExtendedAttributes = 16,
        ReadAttributes = 128,
        WriteAttributes = 256,
        Write = 274,
        Delete = 65536,
        ReadPermissions = 131072,
        Read = 131209,
        ReadWrite = 131483,
        ChangePermissions = 262144,
        TakeOwnership = 524288,
        Synchronize = 1048576,
        FullControl = 2032031,
        AccessSystemSecurity = 16777216
    }
}

- 파이프에 대한 추가적인 권한 설정

TokenImpersonationLevel 열거형

 

TokenImpersonationLevel Enum (System.Security.Principal)

Defines security impersonation levels. Security impersonation levels govern the degree to which a server process can act on behalf of a client process.

learn.microsoft.com

namespace System.Security.Principal
{
    public enum TokenImpersonationLevel
    {
        None = 0,
        Anonymous = 1,
        Identification = 2,
        Impersonation = 3,
        Delegation = 4
    }
}

- 서버 프로세스가 클라이언트 프로세스의 권한을 가장하는 것에 대한 설정
- 책에는 내용이 없고 검색해보니 ASP가 나오는데... 아마 클라이언트의 설정을 배껴오는? 그런 류의 설정인듯.

 

예제

using System;
using System.IO;
using System.IO.Pipes;
using System.Text;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            bool isServer = true;
            
            if (isServer)
            {
                // 메시지 모드로 인스턴스를 생성
                using (var npss = new NamedPipeServerStream("myPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message))
                {
                    // 클라이언트의 접속 대기
                    npss.WaitForConnection();

                    // UTF8로 인코딩해서 전송
                    byte[] byteMessage = Encoding.UTF8.GetBytes("안녕하세요 반갑습니다!");
                    npss.Write(byteMessage, 0, byteMessage.Length);

                    // 클라이언트의 메시지를 전송 받음
                    Console.WriteLine(Encoding.UTF8.GetString(ReadMessage(npss)));
                }
            }
            else
            {
                using (var npcs = new NamedPipeClientStream("myPipe"))
                {
                    // 서버로 접속
                    npcs.Connect();

                    // 읽기 모드를 메시지로 설정
                    npcs.ReadMode = PipeTransmissionMode.Message;

                    // 스트림을 읽어와 출력
                    Console.WriteLine(Encoding.UTF8.GetString(ReadMessage(npcs)));

                    // UTF8로 인코딩해서 전송
                    byte[] byteMessage = Encoding.UTF8.GetBytes("메시지 잘 받았습니다!");
                    npcs.Write(byteMessage, 0, byteMessage.Length);
                }      
            }

            Console.WriteLine("아무키나 눌러 종료!");
            Console.ReadKey(true);
        }

        static byte[] ReadMessage(PipeStream ps)
        {
            // 배열로의 복사를 용이하게 하기 위한 메모리 스트림
            var ms = new MemoryStream();

            // 버퍼 사이즈는 4KB
            var buffer = new byte[0x1000];

            // 1. 파이프 스트림에서 읽어서 버퍼에 저장
            // 2. 메모리 스트림에 버퍼에 있던 내용을 저장
            // 3. 남은 메시지가 있다면 1~2를 반복
            do
            {
                ms.Write(buffer, 0, ps.Read(buffer, 0, buffer.Length));
            }
            while (!ps.IsMessageComplete);

            // 바이트 배열로 만들어서 리턴
            return ms.ToArray();
        }
    }
}
반응형

'C#' 카테고리의 다른 글

[C#] PipeStream  (0) 2023.12.01
[C#] MemoryStream  (0) 2023.11.24
[C#] FileStream  (0) 2023.11.20
[C#] Stream  (0) 2023.11.17
[C#] Task  (0) 2023.11.06
[C#] Thread  (0) 2023.11.01
[C#] Stopwatch  (0) 2023.10.30
[C#] PerformanceCounter, PerformanceCounterCategory  (0) 2023.10.28