Пример именованных каналов
Как написать простой-минимум, необходимый для его работы-тестовое приложение, которое иллюстрирует, как использовать IPC/именованные каналы?
например, как написать консольное приложение, в котором программа 1 говорит "Hello World" программе 2, а программа 2 получает сообщение и отвечает "Roger That" программе 1.
4 ответов:
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(); } }); } } }
для тех, кто новичок в IPC и именованных каналах, я нашел следующий пакет 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();лучшая вещь об этом для меня является то, что в отличие от принятого ответа здесь, он поддерживает несколько клиентов, обращающихся к одному сервер.
вы можете фактически писать в именованный канал, используя его имя, кстати.
Откройте командную оболочку от имени администратора, чтобы обойти ошибку по умолчанию "доступ запрещен":
echo Hello > \.\pipe\PipeName
FYI dotnet core на linux не поддерживает namedpipes, попробуйте tcplistener вместо этого, если вы находитесь на linux
этот код имеет клиент туда и обратно байт.
- клиент пишет байт
- сервер считывает байт
- сервер пишет байт
- клиент считывает байт
DotNet Core 2.0 Server ConsoleApp
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 <-- }); } } }
Comments