命名管道(NamedPipe)是伺服器程序和一個或多個客戶程序之間通信的單向或雙向管道。不同于匿名管道的是:命名管道可以在不相關的程序之間和不同計算機之間使用,伺服器建立命名管道時給它指定一個名字,任何程序都可以通過該名字打開管道的另一端,根據給定的權限和伺服器程序通信。命名管道提供了相對簡單的程式設計接口,使通過網絡傳輸資料并不比同一計算機上兩程序之間通信更困難,不過如果要同時和多個程序通信它就力不從心了。
最近做項目需要在C++和C#程式之間進行通信,查了好多資料,本來覺得挺複雜,其實弄明白之後很簡單。C++與C#都是Windows平台的,進行管道通信其實都是調用系統API隻不過都是封裝好了的,兩者之間寫的通信都是相通的,隻要建立的管道名相同即可。比如用C++建立出服務端C++Sever和用戶端C++Cliet,他們之間可以直接收發消息,同時C#建立出服務端C#Sever和用戶端C#Cliet可以互相發消息。都實作之後,用C++Sever和C#Client組合或者C++Client和C#Sever組合使用基本是沒有問題的,可能傳輸時有字元編碼問題,可以調試解決。以下是我寫的C#服務端和用戶端的兩個控制台程式。
服務端:
class Program
{
static void Main(string[] args)
{
WaitData();
}
private static void WaitData()
{
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("mynamedpipe", PipeDirection.InOut, ))//建立管道
{
try
{
pipeServer.WaitForConnection();//等待用戶端連接配接
pipeServer.ReadMode = PipeTransmissionMode.Byte;
Console.WriteLine("sucess connected?"+pipeServer.IsConnected);
StreamReader sr = new StreamReader(pipeServer);//擷取管道輸入流
StreamWriter sw = new StreamWriter(pipeServer);//擷取管道輸出流
string result;
while (true)//循環接收用戶端消息
{
result = sr.ReadLine();
if (result == null || result == "bye")
break;
Console.WriteLine(result);
sw.WriteLine("I'm Sever!");//傳回用戶端資訊
sw.Flush();//清除緩存流,注意必須有這一步,否則會造成管道堵塞
}
Console.ReadKey();
}
catch (IOException e)
{
throw e;
}
}
}
}
用戶端:
class Program
{
static void Main(string[] args)
{
StartClient();
Console.ReadKey();
}
public static void StartClient()
{
string input;
try
{
using (NamedPipeClientStream pipeStream = new NamedPipeClientStream("localhost", "mynamedpipe"))//與服務端管道名一緻,如果連接配接C++服務端,名稱一緻即可,“localhost”可以更換為IP位址,也可以進行網絡通信
{
pipeStream.Connect();//連接配接服務端
if (!pipeStream.IsConnected)
{
Console.WriteLine("Failed to connect ....");
return;
}
StreamWriter sw = new StreamWriter(pipeStream);
StreamReader sr = new StreamReader(pipeStream);
while (true)//循環輸入
{
input = Console.ReadLine();
Console.WriteLine("SendMessage:" + input);
sw.WriteLine(input);//傳遞消息到服務端
sw.Flush();//注意一定要有,同服務端一樣
string temp = "";
temp = sr.ReadLine();//擷取服務端傳回資訊
Console.WriteLine("replyContent:" + temp );
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message+"\n"+e.StackTrace);
}
}
}
需要注意的問題:
1.管道通信為半雙工通信,資訊的進出都是從一個管道進出,類似對講機,資訊要麼進要麼出,有時候寫不好就會造成阻塞,是以往流裡面寫完東西需要flush().
2.如果C++與C#通信,C++沒有flush()函數,在傳遞的字元串中加上\n即可.
3.傳輸過程注意編碼問題.