1

我有一个 WCF 命名管道服务器、一个非 WCF 命名管道服务器、一个 WCF 命名管道客户端和一个非 wcf 命名管道客户端。

非 wcf 客户端可以连接到两台服务器。wcf 客户端只能连接到 wcf 服务器。当我尝试将它连接到非 wcf 客户端时,我得到了这个异常。

Unhandled Exception: System.ServiceModel.EndpointNotFoundException: There was no endpoint
listening at net.pipe://localhost/PipePlusFive that could accept the message. This is 
often caused by an incorrect address or SOAP action. See InnerException,
if present, for more details. ---> System.IO.PipeException: The pipe endpoint 
'net.pipe://localhost/PipePlusFive' could not be found on your local machine.

--- 内部异常堆栈跟踪结束 ---

据此,管道实际名称是存储在内存映射文件中的 guid。我假设这是为 wcf 客户端和服务器自动处理的。对于非 wcf 服务器,我创建内存映射文件,向其写入 guid,然后使用该 guid 作为名称创建管道。在非 wcf 客户端中,我打开内存映射文件,从中读取管道名称,然后使用该名称连接到管道。然后,事实上我可以使用非 wcf 客户端连接到两台服务器而不进行任何更改,这让我相信我在服务器和客户端上都正确地实现了这部分。

此外,当我启动非 wcf 服务器然后启动 wcf 服务器时,第二个崩溃表明它无法侦听该管道名称,因为另一个端点已经在侦听。

我想知道为什么当非 wcf 客户端可以找到两者时 wcf 客户端找不到非 wcf 服务器?除了我链接到的博客中描述的内容之外,wcf 还有其他东西可以用来找到终点吗?

更新:

这是我用于 WCF 客户端的代码:

 class Program
{
    static void Main(string[] args)
    {
        ChannelFactory<IPlusFive> pipeFactory =
            new ChannelFactory<IPlusFive>(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress("net.pipe://localhost/PipePlusFive"));

        IPlusFive pipeProxy = pipeFactory.CreateChannel();

        while (true)
        {
            string str = Console.ReadLine();
            if (str.Equals("q"))
            { return; }
            Console.WriteLine(pipeProxy.PlusFive(Int32.Parse(str)));
        }
    }
}

这是我用于 WCF 服务器的代码:

class Program
{
    static void Main(string[] args)
    {
        var inst = new PlusFiver();
        using (ServiceHost host = new ServiceHost(inst,
            new Uri[] { new Uri("net.pipe://localhost") }))
        {
            host.AddServiceEndpoint(typeof(IPlusFive), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), "PipePlusFive");
            host.Open();
            Console.WriteLine("Service is Available. Press enter to exit.");
            Console.ReadLine();
            host.Close();
        }
    }
}

这是我用于非 WCF 服务器的代码:

  class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Creating Memory Mapped file...");
        string fileName = GenerateFileMapName(String.Empty);
        Guid pipeName = Guid.NewGuid();
        Console.WriteLine(" writing pipe name: " + pipeName.ToString("D"));
        MemoryMappedFile mmf = null;
        var messageList = new List<byte>();
        try
        {
            mmf = WritePipeName(fileName, pipeName);
            Console.WriteLine("Creating Named Pipe");
            Console.WriteLine("Pipe Name: " + GetPipeNameFromMappedFile(fileName, mmf));
            using (var pipe = new NamedPipeServerStream(pipeName.ToString("D"), PipeDirection.InOut))
            {
                Console.WriteLine("pipe created");
                Console.WriteLine("Waiting for connection");
                pipe.WaitForConnection();
                Console.WriteLine("Received Connection");
                Console.WriteLine("Waiting to receive data");
                var bytes = new byte[7];
                pipe.Read(bytes, 0, 7);
                messageList.AddRange(bytes);
                bytes = new byte[messageList[6]];
                pipe.Read(bytes, 0, messageList[6]);
                messageList.AddRange(bytes);
                bytes = new byte[2];
                pipe.Read(bytes, 0, 2);
                messageList.AddRange(bytes);
                messageList.Add((byte)pipe.ReadByte());
                pipe.WriteByte(0x0b);
                WriteList(messageList);
                Console.WriteLine("Finished reading from pipe");
                PrintBytes(bytes);
                Console.WriteLine("Closing Connection");
                pipe.Disconnect();
                Console.WriteLine("Pipe disconnected");
                //Console.Read();
            }
        }
        finally
        {
            mmf.Dispose();
        }

    }

    private static void WriteList(List<byte> messageList)
    {
        foreach (var b in messageList)
        {
            Console.Write(b.ToString("x2") + " ");
        }
        Console.WriteLine();
    }

    private static void PrintBytes(byte[] bytes)
    {
        foreach (var b in bytes)
        {
            Console.Write(b.ToString("x2") + " ");
        }
        Console.WriteLine();
    }

    private static string GenerateFileMapName(string uri)
    {
        return "net.pipe:EbmV0LnBpcGU6Ly8rLw==";
    }

    private static MemoryMappedFile WritePipeName(string fileName, Guid pipeName)
    {
        var mmf = MemoryMappedFile.CreateNew(fileName, pipeName.ToByteArray().Count());

            Console.WriteLine("Memory Mapped File Created.");
            using (var accessor = mmf.CreateViewAccessor(4, 45))
            {
                Console.WriteLine("Writing pipe name to file");
                accessor.Write(0, ref pipeName);
                Console.WriteLine("Finished writing pipe name to file");
            }
        return mmf;
    }

    private static string GetPipeNameFromMappedFile(string filename, MemoryMappedFile mmf)
    {
        Guid pipeName;
        using (var accessor = mmf.CreateViewAccessor(4, 45))
        {

            accessor.Read<Guid>(0, out pipeName);
        }
        return pipeName.ToString("D");
    }
}
4

1 回答 1

0

WCF 端点 netNamedPipeBinding 旨在连接到 WCF 命名管道服务器。当 WCF 客户端使用这种类型的绑定建立连接时,它会进行与您提到的文章中指定的相同的准备工作。该帖子将澄清其余细节。

于 2012-08-14T21:40:34.937 回答