應答式進程間通信
全體
- 應答式是指服務端開啟管道連接并等待連接,客戶端寫入請求,服務端讀取請求,處理后寫入應答,客戶端讀取應答。最后關閉管道。
- 通信數據為XML形式,寫入管道前將對象XML序列化,讀取時XML反序列化得到對象。
- 使用XML的原因為.net版本較低,不使用第三方庫則不支持JSON,不得以使用。雖然JSON使用更為方便。
- 由于管道為最后關閉,所以服務端在讀取請求時,不能讀到最后,否則將繼續等待客戶端繼續寫入,而客戶端并不再寫入,最終服務端線程停留在等待客戶端寫入而阻塞。
- 所以管道中的寫入與讀取時,使用WriteLine和ReadLine,每次只寫一行,讀一行。XML序列化時,取消掉所有的換行。
- WriteLine方法中將字符串寫入該流,后跟行結束符(換行符)。所以讀取一行并沒有讀到末尾。
服務端
public class NPipeServer
{
private const string pipeName = "MyPipe"; // 定義管道名稱
public void Start()
{
while (true)
{
try {
using (var server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous))
{
Console.WriteLine("服務器已啟動,等待連接...");
server.WaitForConnection();
using (StreamWriter writer = new StreamWriter(server))
using (StreamReader reader = new StreamReader(server))
{
string request = reader.ReadLine();
Console.WriteLine("收到客戶端消息: " + request);
MyObject myObject = MyObject.DeserializeFromXml(request);
// 處理請求并準備應答
string response = ProcessRequest(request);
// 將應答寫回給客戶端
writer.WriteLine(response);
writer.Flush();
}
}
} catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
private static string ProcessRequest(string request)
{
// 在這里實現處理邏輯,比如計算、查詢數據庫等
return $"已處理您的請求:{request},這里是應答...";
}
}
客戶端
public class NPipeClient
{
private const string pipeName = "MyPipe";
public void SendRequest(MyObject myObject)
{
try {
using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut))
{
client.Connect(5000); // 等待最多5秒連接到服務器
using (StreamWriter writer = new StreamWriter(client))
using (StreamReader reader = new StreamReader(client))
{
// 發送請求
writer.WriteLine(myObject.SerializeToXml());
writer.Flush();
// 接收應答
string response = reader.ReadLine();
Console.WriteLine("從服務器接收到應答: " + response);
}
}
} catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
通信數據
[Serializable]
public class MyObject
{
public string Msg { get; set; }
public int Data { get; set; }
public string SerializeToXml()
{
var serializer = new XmlSerializer(typeof(MyObject));
var settings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
NewLineHandling = NewLineHandling.None,
Encoding = Encoding.UTF8
};
XmlSerializerNamespaces _namespaces = new XmlSerializerNamespaces(
new XmlQualifiedName[] {
new XmlQualifiedName(string.Empty, "aa")
});
using (var stringWriter = new StringWriter())
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, this, _namespaces);
string xmlString = stringWriter.ToString().Replace(@"\r\n","").Replace(@"\n","");
return xmlString;
}
}
public static MyObject DeserializeFromXml(string xml)
{
var serializer = new XmlSerializer(typeof(MyObject));
using (var textReader = new StringReader(xml))
{
return (MyObject)serializer.Deserialize(textReader);
}
}
}