命名管道示例

我如何编写一个简单的——仅仅是它工作所需的最低限度的——说明如何使用 IPC/命名管道的测试应用程序?

例如,如何写一个控制台应用,其中程序1对程序2说“ Hello World”,程序2接收消息并对程序1回复“ Roger That”。

149324 次浏览
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();

对我来说最好的事情是,与这里接受的答案不同,它支持多个客户端与单个服务器通信。

实际上,您可以使用命名管道的名称(btw)写入命名管道。

以管理员身份打开一个命令 shell,以避免默认的“拒绝访问”错误:

echo Hello > \\.\pipe\PipeName

Linux dotnet 核心不支持 namedtube!

如果部署到 Linux,请尝试 TcpListener

这段 NamedPipeClient/Server 代码往返于一个字节到一个服务器。

  • 客户端写入字节
  • 服务器读取字节
  • 服务器写入字节
  • 客户端读取字节

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客户端控制应用程序

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