Exemplo de pipes nomeados

Como faço para escrever um simples – mínimo necessário para que ele funcione – aplicativo de teste que ilustra como usar IPC / Named Pipes?

Por exemplo, como escrever um aplicativo de console no qual o Programa 1 diz “Hello World” ao Programa 2 e o Programa 2 recebe mensagens e responde “Roger That” ao Programa 1.

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

Para alguém que é novo no IPC e no Named Pipes, achei o seguinte pacote do NuGet uma grande ajuda.

GitHub: Invólucro de Tubulação Nomeado para .NET 4.0

Para usar primeiro instale o pacote:

 PS> Install-Package NamedPipeWrapper 

Em seguida, um exemplo de servidor (copiado do link):

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

Exemplo de cliente:

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

A melhor coisa para mim é que, ao contrário da resposta aceita, ela suporta vários clientes conversando com um único servidor.

Você pode realmente gravar em um pipe nomeado usando seu nome, btw.

Abra um shell de comando como Administrador para contornar o erro padrão “Acesso negado”:

 echo Hello > \\.\pipe\PipeName 

FYI dotnet core no linux não suporta namedpipes, tente tcplistener se você estiver no linux

Este código tem um cliente de ida e volta um byte.

  • Cliente escreve byte
  • O servidor lê byte
  • Servidor escreve byte
  • Cliente lê byte

Console do servidor 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 Client 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 < -- }); } } }