명명 된 파이프의 예


131

IPC / 명명 된 파이프를 사용하는 방법을 보여주는 간단한 테스트 (최소한의 최소한의 작동) 테스트 응용 프로그램을 작성하려면 어떻게해야합니까?

예를 들어, 프로그램 1이 프로그램 2에 "Hello World"라고 말하고 프로그램 2가 메시지를 수신하고 "Roger That"을 프로그램 1에 응답하는 콘솔 응용 프로그램을 작성하는 방법은 무엇입니까?

답변:


166
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            StartServer();
            Task.Delay(1000).Wait();


            //Client
            var client = new NamedPipeClientStream("PipesOfPiece");
            client.Connect();
            StreamReader reader = new StreamReader(client);
            StreamWriter writer = new StreamWriter(client);

            while (true)
            {
                string input = Console.ReadLine();
                if (String.IsNullOrEmpty(input)) break;
                writer.WriteLine(input);
                writer.Flush();
                Console.WriteLine(reader.ReadLine());
            }
        }

        static void StartServer()
        {
            Task.Factory.StartNew(() =>
            {
                var server = new NamedPipeServerStream("PipesOfPiece");
                server.WaitForConnection();
                StreamReader reader = new StreamReader(server);
                StreamWriter writer = new StreamWriter(server);
                while (true)
                {
                    var line = reader.ReadLine();
                    writer.WriteLine(String.Join("", line.Reverse()));
                    writer.Flush();
                }
            });
        }
    }
}

1
@JordanTrainor 죄송합니다. .Net 4.5에 있습니다. 사용 가능Thread.Sleep
LB

2
@Gusdor 나는 동기화 권한을 사용할 수있었습니다. 그러나 읽기가 더 어려울 것입니다. NamedPipes 사용 방법에 대한 아이디어를 제공하는 것으로 충분하다고 생각합니다.
LB

2
당신은 파이프가 닫히고 하나 개의 읽기 후,이 답변을 확인하는 문제가있는 경우 : stackoverflow.com/a/895656/941764을
jgillich

11
당신이 .NET 4.5을 사용하는 경우, 당신은 할 수 있습니다 교체 Task.Factory.StartNew와 함께Task.Run .
Rudey

2
처분해야 합니까 reader/ writer? 그렇다면 그 중 하나만 처리합니까? 둘 다 동일한 스트림에 연결된 예제를 본 적이 없습니다.
JoshVarty

21

IPC 및 Named Pipes를 처음 사용하는 사람에게는 다음 NuGet 패키지가 큰 도움이된다는 것을 알았습니다.

GitHub : .NET 4.0 용 명명 된 파이프 래퍼

패키지를 먼저 설치하려면 :

PS> Install-Package NamedPipeWrapper

그런 다음 예제 서버 (링크에서 복사) :

var server = new NamedPipeServer<SomeClass>("MyServerPipe");
server.ClientConnected += delegate(NamedPipeConnection<SomeClass> conn)
    {
        Console.WriteLine("Client {0} is now connected!", conn.Id);
        conn.PushMessage(new SomeClass { Text: "Welcome!" });
    };

server.ClientMessage += delegate(NamedPipeConnection<SomeClass> conn, SomeClass message)
    {
        Console.WriteLine("Client {0} says: {1}", conn.Id, message.Text);
    };

server.Start();

클라이언트 예 :

var client = new NamedPipeClient<SomeClass>("MyServerPipe");
client.ServerMessage += delegate(NamedPipeConnection<SomeClass> conn, SomeClass message)
    {
        Console.WriteLine("Server says: {0}", message.Text);
    };

client.Start();

나에게 가장 좋은 점은 여기서 받아 들인 대답과 달리 단일 서버와 대화하는 여러 클라이언트를 지원한다는 것입니다.


5
프로덕션에는이 NuGet 패키지를 권장하지 않습니다. 나는 그것을 구현했으며 몇 가지 버그가 있습니다. 주로 파이프의 다른 쪽 끝에서 메시지가 완전히 수신 된 시점을 알 수 없기 때문에 (연결이 끊어 지거나 연결이 너무 빨리 끝납니다 (코드를 확인하십시오) github 당신이 나를 믿지 않으면, "WaitForPipeDrain"은 필요할 때 호출되지 않습니다.) 게다가 너무 많은 문제 때문에 하나의 클라이언트 만 듣고있을 때도 여러 클라이언트가 있습니다. 정말 사용하기 쉬웠 기 때문에 슬프다. 적은 옵션으로 처음부터 다시 작성해야했습니다.
Micaël Félix

유감스럽게도, 유감스럽게도 원래의 관리자가 수년 동안 프로젝트를 업데이트하지 않았지만, 다행스럽게도 많은 포크가 존재하지만 논의 한 문제를 해결합니다.
Martin Laukkanen

2
@MartinLaukkanen : 안녕하세요, NamedPipeWrapper를 사용할 계획입니다.이 버그를 수정하고있는 포크를 알고 계십니까? 감사합니다
Whiletrue

17

실제로 btw라는 이름을 사용하여 명명 된 파이프에 쓸 수 있습니다.

기본 "액세스가 거부되었습니다"오류를 해결하려면 관리자 권한으로 명령 셸을 엽니 다.

echo Hello > \\.\pipe\PipeName

3

리눅스의 FYI 닷넷 코어는 namedpipes를 지원하지 않습니다. 리눅스에 있다면 대신 tcplistener를 사용해보십시오

이 코드에는 클라이언트 왕복 바이트가 있습니다.

  • 클라이언트 쓰기 바이트
  • 서버가 바이트를 읽습니다.
  • 서버 쓰기 바이트
  • 클라이언트가 바이트를 읽습니다.

DotNet Core 2.0 서버 콘솔

using System;
using System.IO.Pipes;
using System.Threading.Tasks;

namespace Server
{
    class Program
    {
        static void Main(string[] args)
        {
            var server = new NamedPipeServerStream("A", PipeDirection.InOut);
            server.WaitForConnection();

            for (int i =0; i < 10000; i++)
            {
                var b = new byte[1];
                server.Read(b, 0, 1); 
                Console.WriteLine("Read Byte:" + b[0]);
                server.Write(b, 0, 1);
            }
        }
    }
}

DotNet Core 2.0 클라이언트 ConsoleApp

using System;
using System.IO.Pipes;
using System.Threading.Tasks;

namespace Client
{
    class Program
    {
        public static int threadcounter = 1;
        public static NamedPipeClientStream client;

        static void Main(string[] args)
        {
            client = new NamedPipeClientStream(".", "A", PipeDirection.InOut, PipeOptions.Asynchronous);
            client.Connect();

            var t1 = new System.Threading.Thread(StartSend);
            var t2 = new System.Threading.Thread(StartSend);

            t1.Start();
            t2.Start(); 
        }

        public static void StartSend()
        {
            int thisThread = threadcounter;
            threadcounter++;

            StartReadingAsync(client);

            for (int i = 0; i < 10000; i++)
            {
                var buf = new byte[1];
                buf[0] = (byte)i;
                client.WriteAsync(buf, 0, 1);

                Console.WriteLine($@"Thread{thisThread} Wrote: {buf[0]}");
            }
        }

        public static async Task StartReadingAsync(NamedPipeClientStream pipe)
        {
            var bufferLength = 1; 
            byte[] pBuffer = new byte[bufferLength];

            await pipe.ReadAsync(pBuffer, 0, bufferLength).ContinueWith(async c =>
            {
                Console.WriteLine($@"read data {pBuffer[0]}");
                await StartReadingAsync(pipe); // read the next data <-- 
            });
        }
    }
}

2 개의 프로세스에 이와 같은 명명 된 파이프를 사용하면 다음과 같은 결과를 System Unauthorized Accesss Exception - path is denied

어쩌면 관리자 권한으로 실행할 수 있습니까?
패트릭
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.