应答式进程间通信
全体
- 应答式是指服务端开启管道连接并等待连接,客户端写入请求,服务端读取请求,处理后写入应答,客户端读取应答。最后关闭管道。
- 通信数据为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);
}
}
}
标签:string,C#,NamePipe,间通信,WriteLine,new,var,using,public
From: https://www.cnblogs.com/xs1987/p/18106573