目錄結構:
contents structure
[+]
管道為進程間通信提供了一種可能。管道分為兩種,一種是匿名管道,另一種是命名管道。
1.匿名管道(anonymous pipe)
匿名管道,匿名管道只提供在本地電腦進程間的通信。匿名管道比命名管道花費的開銷更少,但提供的服務也比命名管道的少。匿名管道是單向的,而且不能用於網絡通信。匿名管道只支持單服務器實例。
匿名管道不支持消息傳輸模式(PipeTransmissionMode.Message),僅支持字節傳輸模式(PipeTransmissionMode.Byte)。
創建匿名管道需要使用AnonymousPipeClientStream和AnonymousPipeServerStream類,下面的案例展示了匿名的管道的用法。
首先創建一個PipeServer.cs文件,其內容如下:

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PipeServer { class Program { static void Main(string[] args) { Process pipeClient1=new Process(); pipeClient1.StartInfo.FileName = @"PipeClient.exe"; //AnonymousPipeServerStream is an one-way pipe. in other words it's only support PipeDirection.In or PipeDirection.Out. //in this program, we use PipeDirection.Out for send data to clients. using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable)) { //send the client handle that from AnonymousPipeServerStream to client pipeClient1.StartInfo.Arguments = pipeServer.GetClientHandleAsString(); pipeClient1.StartInfo.UseShellExecute = false; pipeClient1.Start(); //closes the local copy of the AnonymousPipeClientStream object's handle //this method must be call after the client handle has been passed to the client //if this method isn't called, then the AnonymousPipeServerStream will not receive notice when client dispose of it's PipeStream object pipeServer.DisposeLocalCopyOfClientHandle(); try { using(StreamWriter sw=new StreamWriter(pipeServer)){ //automatic flush sw.AutoFlush = true; sw.WriteLine("SYNC"); //it'll block util the other end of pipe has been read all send bytes pipeServer.WaitForPipeDrain(); String temp=null; while(true){ temp=Console.ReadLine(); //send message to pipeclient from console sw.WriteLine(temp); //it'll block util the other end of pipe has been read all send bytes pipeServer.WaitForPipeDrain(); if(temp=="exit"){ break; } } } } catch (IOException e) { Console.WriteLine("[server] exception:{0}",e.Message); } } pipeClient1.WaitForExit(); pipeClient1.Close(); } } }
然后創建PipeClient.cs文件,內容如下:

using System; using System.Collections.Generic; using System.IO; using System.IO.Pipes; using System.Linq; using System.Text; using System.Threading.Tasks; class Program { static void Main(string[] args) { using (PipeStream pipeClient = new AnonymousPipeClientStream(PipeDirection.In, args[0])) { using (StreamReader sr = new StreamReader(pipeClient)) { String temp = null; Console.WriteLine("[client] wait for sync ..."); do{ temp = sr.ReadLine(); }while(!temp.StartsWith("SYNC")); Console.WriteLine("client in"); while ((temp = sr.ReadLine()) != null) { Console.WriteLine("[client] receive message: " + temp); if(temp=="exit"){ break; } } } Console.Write("[client] Press Enter to exist..."); Console.ReadLine(); } } }
這里只展示一個服務端一個客戶端,但實際中可以有多個客戶端。PipeClient.cs和PipeServer.cs應該在同一個文件夾下面,具體的路徑由PipeServer.cs中加載客戶端的路徑決定,本例中是在同一路徑下。然后可以使用csc將其都編譯為可執行文件。
2.命名管道(named pipe)
命名管道和匿名管道的功能相似,但他們有如下兩點區別:
- 命名管道既可以支持直接傳輸模式(PipeTransmissionMode.Byte),也可以支持消息傳輸模式(PipeTransmissionMode.Message)
- 命名管道既可以用於本地進程間的通信,也可以用於網絡通信。
創建命名管道需要使用NamedPipeServerStream和NamedPipeClientStream類,下面的案例展示了命名管道的用法:
PipeServer.cs

using System; using System.Collections.Generic; using System.IO; using System.IO.Pipes; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace PipeServer { class Program { static void Main(string[] args) { Console.WriteLine("Waiting client to connect...\n"); using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut)) { //wait client to connect pipeServer.WaitForConnection(); Console.WriteLine("[server] a client connected"); StreamReader reader = new StreamReader(pipeServer); StreamWriter writer = new StreamWriter(pipeServer); writer.AutoFlush = true; String line = null; while ((line = reader.ReadLine()) != null) { Console.WriteLine("[server] receive message:"+line); writer.WriteLine("I'm fine"); pipeServer.WaitForPipeDrain(); if ("line" == "EXIT") { break; } } }; Console.ReadLine(); } } }
PipeClient.cs

using System; using System.Collections.Generic; using System.IO; using System.IO.Pipes; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PipeClient { class Program { static void Main(string[] args) { //initialize NamePipeClientStream with serverName,pipeName,pipeDirection using (NamedPipeClientStream pipeClient = new NamedPipeClientStream("host path", "testpipe", PipeDirection.InOut)) { Console.WriteLine("[client] Attemping to connect to pipe..."); pipeClient.Connect(); Console.WriteLine("[client] connected to pipe"); Console.WriteLine("[client] There are currently {0} pipe server instances open.",pipeClient.NumberOfServerInstances); StreamWriter writer = new StreamWriter(pipeClient); writer.AutoFlush = true; StreamReader reader = new StreamReader(pipeClient); String temp = ""; while (true) { temp = Console.ReadLine(); //send to server writer.WriteLine(temp); pipeClient.WaitForPipeDrain(); //read from server Console.WriteLine("[client] read message from server:"+reader.ReadLine()); if (temp == "EXIT") { break; } } } Console.ReadLine(); } } }
這里需要注意,"."代表本機地址。如果需要到其他服務器,替換就好了。