如何等待NamedPipeServer的响应?

cod*_*ero 4 c# named-pipes

我有以下客户端代码,我将内容写入Server管道,我能够在侧面读取它,Server但在我回复之前,客户端已经尝试读取仍然为空的管道。你怎么waitNamedPipeClientStream

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;
}
Run Code Online (Sandbox Code Playgroud)

我认为我不应该使用WaitForPipeDrain,但是我没有其他选择可以等待,或者知道什么时候可以阅读?有很多示例,但没有一个显示客户端等待响应的正确方法。

微软显示的示例似乎在发送字符串数据时使用ReadLine()和利用EOL字符,但我正在处理byte[]数据(“hello world”只是为了获取一些字节)。

Ňuf*_*Ňuf 7

您无需等待数据。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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

服务器:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)