如何等待 NamedPipeServer 的响应?
How to wait for response from NamedPipeServer?
我有以下客户端代码,我将内容写入 Server
管道,我能够在 Server
端读取它,但在我回复之前,客户端已经尝试读取仍然是空的管道。你怎么wait
就NamedPipeClientStream
?
using (NamedPipeClientStream pipe = new NamedPipeClientStream(".", pipename, PipeDirection.InOut))
{
pipe.Connect(5000);
pipe.ReadMode = PipeTransmissionMode.Byte;
byte[] ba = Encoding.Default.GetBytes("hello world");
pipe.Write(ba, 0, ba.Length);
var result = await Task.Run(() => {
// this would return as soon as Server finished reading
// but then server hasn't wrote anything back yet
pipe.WaitForPipeDrain();
// sample code on how i am planning to read, not tested,
// since the pipe is still empty at this point
using (StreamReader reader = new StreamReader(pipe))
using (MemoryStream ms = new MemoryStream())
{
reader.BaseStream.CopyTo(ms);
return Encoding.Default.GetString(ms.ToArray());
}
});
return result;
}
我认为我不应该使用 WaitForPipeDrain
但是我没有其他选择可以等待,或者知道什么时候可以阅读?那里有很多示例,但其中 none 显示了客户端等待响应的正确方法。
Microsoft 显示的示例似乎在使用 ReadLine()
并在发送字符串数据时利用 EOL
字符,但我处理的是 byte[]
数据("hello world"只是为了获取一些字节)。
您无需等待数据。 NamedPipeClientStream
表示一个字节流(它派生自 System.IO.Stream
),如果当前没有数据可用,从管道(或从包装该管道的 StreamReader
读取)将简单地阻塞直到数据到达.
对于传输文本数据,用StreamReader.ReadLine()
读和用StreamWriter.WriteLine()
写就可以了。要传输二进制数据,您可以将二进制数据编码为文本形式(例如使用 base64 编码)并继续使用 StreamReader.ReadLine()
/ StreamWriter.WriteLine()
。或者您可以将服务器和客户端管道设置为 PipeStream.TransmissionMode 到 Message
模式,并将每个字节数组作为单个消息传输,如下所示(为简洁起见省略了错误检查):
客户:
class Client
{
static async Task Main(string[] args)
{
using (NamedPipeClientStream pipe = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut))
{
pipe.Connect(5000);
pipe.ReadMode = PipeTransmissionMode.Message;
byte[] ba = Encoding.Default.GetBytes("hello world");
pipe.Write(ba, 0, ba.Length);
var result = await Task.Run(() => {
return ReadMessage(pipe);
});
Console.WriteLine("Response received from server: " + Encoding.UTF8.GetString(result));
Console.ReadLine();
}
}
private static byte[] ReadMessage(PipeStream pipe)
{
byte[] buffer = new byte[1024];
using (var ms = new MemoryStream())
{
do
{
var readBytes = pipe.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, readBytes);
}
while (!pipe.IsMessageComplete);
return ms.ToArray();
}
}
}
服务器:
class Server
{
static void Main(string[] args)
{
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream(
"testpipe",
PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Message))//Set TransmissionMode to Message
{
// Wait for a client to connect
Console.Write("Waiting for client connection...");
pipeServer.WaitForConnection();
Console.WriteLine("Client connected.");
//receive message from client
var messageBytes = ReadMessage(pipeServer);
Console.WriteLine("Message received from client: " + Encoding.UTF8.GetString(messageBytes));
//prepare some response
var response = Encoding.UTF8.GetBytes("Hallo from server!");
//send response to a client
pipeServer.Write(response, 0, response.Length);
Console.ReadLine();
}
}
private static byte[] ReadMessage(PipeStream pipe)
{
byte[] buffer = new byte[1024];
using (var ms = new MemoryStream())
{
do
{
var readBytes = pipe.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, readBytes);
}
while (!pipe.IsMessageComplete);
return ms.ToArray();
}
}
}
我有以下客户端代码,我将内容写入 Server
管道,我能够在 Server
端读取它,但在我回复之前,客户端已经尝试读取仍然是空的管道。你怎么wait
就NamedPipeClientStream
?
using (NamedPipeClientStream pipe = new NamedPipeClientStream(".", pipename, PipeDirection.InOut))
{
pipe.Connect(5000);
pipe.ReadMode = PipeTransmissionMode.Byte;
byte[] ba = Encoding.Default.GetBytes("hello world");
pipe.Write(ba, 0, ba.Length);
var result = await Task.Run(() => {
// this would return as soon as Server finished reading
// but then server hasn't wrote anything back yet
pipe.WaitForPipeDrain();
// sample code on how i am planning to read, not tested,
// since the pipe is still empty at this point
using (StreamReader reader = new StreamReader(pipe))
using (MemoryStream ms = new MemoryStream())
{
reader.BaseStream.CopyTo(ms);
return Encoding.Default.GetString(ms.ToArray());
}
});
return result;
}
我认为我不应该使用 WaitForPipeDrain
但是我没有其他选择可以等待,或者知道什么时候可以阅读?那里有很多示例,但其中 none 显示了客户端等待响应的正确方法。
Microsoft 显示的示例似乎在使用 ReadLine()
并在发送字符串数据时利用 EOL
字符,但我处理的是 byte[]
数据("hello world"只是为了获取一些字节)。
您无需等待数据。 NamedPipeClientStream
表示一个字节流(它派生自 System.IO.Stream
),如果当前没有数据可用,从管道(或从包装该管道的 StreamReader
读取)将简单地阻塞直到数据到达.
对于传输文本数据,用StreamReader.ReadLine()
读和用StreamWriter.WriteLine()
写就可以了。要传输二进制数据,您可以将二进制数据编码为文本形式(例如使用 base64 编码)并继续使用 StreamReader.ReadLine()
/ StreamWriter.WriteLine()
。或者您可以将服务器和客户端管道设置为 PipeStream.TransmissionMode 到 Message
模式,并将每个字节数组作为单个消息传输,如下所示(为简洁起见省略了错误检查):
客户:
class Client
{
static async Task Main(string[] args)
{
using (NamedPipeClientStream pipe = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut))
{
pipe.Connect(5000);
pipe.ReadMode = PipeTransmissionMode.Message;
byte[] ba = Encoding.Default.GetBytes("hello world");
pipe.Write(ba, 0, ba.Length);
var result = await Task.Run(() => {
return ReadMessage(pipe);
});
Console.WriteLine("Response received from server: " + Encoding.UTF8.GetString(result));
Console.ReadLine();
}
}
private static byte[] ReadMessage(PipeStream pipe)
{
byte[] buffer = new byte[1024];
using (var ms = new MemoryStream())
{
do
{
var readBytes = pipe.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, readBytes);
}
while (!pipe.IsMessageComplete);
return ms.ToArray();
}
}
}
服务器:
class Server
{
static void Main(string[] args)
{
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream(
"testpipe",
PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Message))//Set TransmissionMode to Message
{
// Wait for a client to connect
Console.Write("Waiting for client connection...");
pipeServer.WaitForConnection();
Console.WriteLine("Client connected.");
//receive message from client
var messageBytes = ReadMessage(pipeServer);
Console.WriteLine("Message received from client: " + Encoding.UTF8.GetString(messageBytes));
//prepare some response
var response = Encoding.UTF8.GetBytes("Hallo from server!");
//send response to a client
pipeServer.Write(response, 0, response.Length);
Console.ReadLine();
}
}
private static byte[] ReadMessage(PipeStream pipe)
{
byte[] buffer = new byte[1024];
using (var ms = new MemoryStream())
{
do
{
var readBytes = pipe.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, readBytes);
}
while (!pipe.IsMessageComplete);
return ms.ToArray();
}
}
}