WCF 命名管道最小示例

Posted

技术标签:

【中文标题】WCF 命名管道最小示例【英文标题】:WCF named pipe minimal example 【发布时间】:2011-11-13 07:08:45 【问题描述】:

我正在寻找 WCF 命名管道的最小示例(我希望有两个最小的应用程序,服务器和客户端,它们可以通过命名管道进行通信。)

Microsoft 有一篇精彩的文章 Getting Started Tutorial 描述了通过 HTTP 的 WCF,我正在寻找关于 WCF 和命名管道的类似内容。

我在网上找了几篇帖子,但都有些“高级”。我需要一些最小的、只有强制性的功能,所以我可以添加我的代码并让应用程序运行。

如何替换它以使用命名管道?

<endpoint address="http://localhost:8000/ServiceModelSamples/Service/CalculatorService"
    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
    contract="ICalculator" name="WSHttpBinding_ICalculator">
    <identity>
        <userPrincipalName value="OlegPc\Oleg" />
    </identity>
</endpoint>

如何替换它以使用命名管道?

// Step 1 of the address configuration procedure: Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");

// Step 2 of the hosting procedure: Create ServiceHost
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);

try

    // Step 3 of the hosting procedure: Add a service endpoint.
    selfHost.AddServiceEndpoint(
        typeof(ICalculator),
        new WSHttpBinding(),
        "CalculatorService");

    // Step 4 of the hosting procedure: Enable metadata exchange.
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    selfHost.Description.Behaviors.Add(smb);

    // Step 5 of the hosting procedure: Start (and then stop) the service.
    selfHost.Open();
    Console.WriteLine("The service is ready.");
    Console.WriteLine("Press <ENTER> to terminate service.");
    Console.WriteLine();
    Console.ReadLine();

    // Close the ServiceHostBase to shutdown the service.
    selfHost.Close();

catch (CommunicationException ce)

    Console.WriteLine("An exception occurred: 0", ce.Message);
    selfHost.Abort();

如何生成客户端以使用命名管道?

【问题讨论】:

你看过***.com/questions/184878/…吗? 【参考方案1】:

我刚刚发现this excellent little tutorial。 链接断开 (Cached version)

我也遵循了微软的教程,这很好,但我也只需要管道。

如您所见,您不需要配置文件和所有那些乱七八糟的东西。

顺便说一句,他同时使用 HTTP 和管道。只需删除所有与 HTTP 相关的代码行,您将获得一个纯管道示例。

【讨论】:

谢谢!此外,当尝试构建使用 web.config 进行配置而不是硬编码配置的服务时,请参阅此 Microsoft 示例:msdn.microsoft.com/en-us/library/ms752253.aspx 链接失效了,还有别的教程吗? 刚刚花了一段时间试图找出“管道已结束”的原因。这是我的解决方案,希望对您有所帮助:***.com/a/49075797/385273【参考方案2】:

试试这个。

这是服务部分。

[ServiceContract]
public interface IService

    [OperationContract]
    void  HelloWorld();


public class Service : IService

    public void HelloWorld()
    
        //Hello World
    

这是代理

public class ServiceProxy : ClientBase<IService>

    public ServiceProxy()
        : base(new ServiceEndpoint(ContractDescription.GetContract(typeof(IService)),
            new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyAppNameThatNobodyElseWillUse/helloservice")))
    

    
    public void InvokeHelloWorld()
    
        Channel.HelloWorld();
    

这里是服务托管部分。

var serviceHost = new ServiceHost
        (typeof(Service), new Uri[]  new Uri("net.pipe://localhost/MyAppNameThatNobodyElseWillUse") );
    serviceHost.AddServiceEndpoint(typeof(IService), new NetNamedPipeBinding(), "helloservice");
    serviceHost.Open();

    Console.WriteLine("Service started. Available in following endpoints");
    foreach (var serviceEndpoint in serviceHost.Description.Endpoints)
    
        Console.WriteLine(serviceEndpoint.ListenUri.AbsoluteUri);
    

【讨论】:

这可能行得通,但不如只为客户端和服务器编辑 app.config 文件那么灵活... 很好,因为通常不希望通过 app.config 文件公开应用程序详细信息。 这是一个很好的例子,但是,永远不要只使用 net.pipe://localhost/ 的基地址。如果你这样做并且机器有任何其他也使用 net.pipe://localhost/ 的程序,那么当你打开它时 ServiceHost 会抛出一个异常。相反,请使用一些独特的东西,例如 net.pipe://localhost/MyAppNameThatNobodyElseWillUse。希望这有助于节省其他人一些时间和挫败感! 这个解决方案效果很好。特别是对于不需要在配置中具有服务引用的内部端点。只需将合约 - 只是接口定义 - 保存在他们自己的程序集中,也许还有 config.xml 中的地址。绑定不太可能发生变化。 我需要在代理的端点地址末尾添加/helloservice【参考方案3】:

查看我的highly simplified Echo example: 它旨在使用基本的 HTTP 通信,但可以通过编辑客户端和服务器的 app.config 文件轻松修改为使用命名管道。进行以下更改:

编辑服务器的 app.config 文件,删除或注释掉 http baseAddress 条目并添加新的 baseAddress 命名管道的条目(称为 net.pipe)。此外,如果您不打算将 HTTP 用于通信协议,请确保 serviceMetadataserviceDebug被注释掉或删除:

<configuration>
    <system.serviceModel>
        <services>
            <service name="com.aschneider.examples.wcf.services.EchoService">
                <host>
                    <baseAddresses>
                        <add baseAddress="net.pipe://localhost/EchoService"/>
                    </baseAddresses>
                </host>
            </service>
        </services>
        <behaviors>
            <serviceBehaviors></serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

编辑客户端的 app.config 文件,以便将 basicHttpBinding 注释掉或删除,以及 netNamedPipeBinding > 条目已添加。您还需要更改 endpoint 条目以使用管道:

<configuration>
    <system.serviceModel>
        <bindings>
            <netNamedPipeBinding>
                <binding name="NetNamedPipeBinding_IEchoService"/>
            </netNamedPipeBinding>
        </bindings>
        <client>
            <endpoint address              = "net.pipe://localhost/EchoService"
                      binding              = "netNamedPipeBinding"
                      bindingConfiguration = "NetNamedPipeBinding_IEchoService"
                      contract             = "EchoServiceReference.IEchoService"
                      name                 = "NetNamedPipeBinding_IEchoService"/>
        </client>
    </system.serviceModel>
</configuration>

上面的例子只能用命名管道运行,但没有什么能阻止你使用多种协议来运行你的服务。 AFAIK,您应该能够让服务器使用命名管道和 HTTP(以及其他协议)运行服务。

此外,客户端 app.config 文件中的绑定也得到了高度简化。除了指定 baseAddress...

之外,您还可以调整许多不同的参数

【讨论】:

链接已失效。【参考方案4】:

我根据互联网上的不同搜索结果创建了这个简单的示例。

public static ServiceHost CreateServiceHost(Type serviceInterface, Type implementation)

  //Create base address
  string baseAddress = "net.pipe://localhost/MyService";

  ServiceHost serviceHost = new ServiceHost(implementation, new Uri(baseAddress));

  //Net named pipe
  NetNamedPipeBinding binding = new NetNamedPipeBinding  MaxReceivedMessageSize = 2147483647 ;
  serviceHost.AddServiceEndpoint(serviceInterface, binding, baseAddress);

  //MEX - Meta data exchange
  ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
  serviceHost.Description.Behaviors.Add(behavior);
  serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexNamedPipeBinding(), baseAddress + "/mex/");

  return serviceHost;

使用上面的 URI,我可以在我的客户端中添加对 Web 服务的引用。

【讨论】:

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

未找到 WCF 命名管道端点

带有命名管道的 WCF:如何允许并行调用?

WCF 命名管道错误:管道已结束。 (109, 0x6d)

WCF 服务命名管道故障

使用命名管道 WCF 服务时通信对象出错

WCF 命名管道 IO 异常 - 管道已结束。 (109, 0x6d)