双向命名管道问题

Posted

技术标签:

【中文标题】双向命名管道问题【英文标题】:bidirectional named pipe question 【发布时间】:2009-08-20 21:54:09 【问题描述】:

我有 2 个应用程序,我想通过 .NET 3.5 上的命名管道进行通信。它是一种请求/响应范例,数据以 XML 格式传输,让我的生活更轻松。有一个侦听器应用程序和一个将请求发布到管道的应用程序。我正在尝试使用双向管道来执行此操作。我遇到的问题是对 StreamReader.ReadToEnd() 的调用似乎没有返回。我该怎么做才能解决这个问题?

监听代码

public Class Listener

    private void ThreadFunc()
    
       var pipe = new NamedPipeServerStream("GuideSrv.Pipe",PipeDirection.InOut);
       var instream = new StreamReader(pipe);
       var outstream = new StreamWriter(pipe);
       while (true)
       
           pipe.WaitForConnection();
           var response = ProcessPipeRequest(instream);
           outstream.Write(response.ToString());
           pipe.Disconnect();
       
    
    private XDocument ProcessPipeRequest(StreamReader stream)
    
        var msg_in = stream.ReadToEnd();  // << This call doesnt return
        var xml_in = XDocument.Parse(msg_in);
        // do some stuff here 
        return new XDocument(....);
      

请求者代码

public XDocument doIt()

    var xml = new XDocument(....);
    using (var pipe = new NamedPipeClientStream(".", "GuideSrv.Pipe", PipeDirection.InOut))
     
        using (var outstream = new StreamWriter(pipe))
        using (var instream = new StreamReader(pipe))
        
            pipe.Connect();
            outstream.Write(xml.ToString());
            xml = XDocument.Parse(instream.ReadToEnd());
        
    
    return xml;

【问题讨论】:

【参考方案1】:

doIt() 中执行outstream.Write(xml.ToString()) 之后,然后尝试从instream 读取。与此同时,您的另一个线程正在stream.ReadToEnd() 中等待。它会永远等待,因为它不知道你已经写完了。据它所知,您可以再次致电outstream.Write() 以写入更多数据。 ReadToEnd() 调用不会返回,直到您真正关闭来自 doIt() 的管道。

您可以通过让他们更智能地相互交流来解决这个问题。例如,您可以将xml.ToString() 的长度写入管道,然后写入字符串。然后在您的阅读器线程中,您首先读取长度,然后读取msg_in,只读取您希望发送的确切字节数,当您全部读取它们时停止,而不是等待管道关闭。

【讨论】:

以上是关于双向命名管道问题的主要内容,如果未能解决你的问题,请参考以下文章

c#命名管道双向通信

命名管道(C#)

C/S模型之命名管道

创建双向管道或任何类似行为的 Unix 方式?

C# 和 Python 之间的命名管道

使用命名管道的两种 C++ 到 C# 通信