WCF命名管道的最小示例


90

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

微软有一篇引人入胜的文章“ 入门指南”,它通过HTTP描述了WCF,而我正在寻找有关WCF和命名管道的类似信息。

我已经在Internet上找到了几篇文章,但是它们有些“高级”。我需要一些最少的东西,只有强制性的功能,因此我可以添加代码并使应用程序正常运行。

如何替换为使用命名管道?

<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();
}

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


Answers:


80

我刚刚找到了这个很棒的小教程 链接断开缓存版本

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

如您所见,您不需要配置文件和所有杂乱的东西。

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


2
谢谢!另外,当尝试构建使用web.config进行配置而不是硬编码配置的服务时,请参见以下Microsoft示例:msdn.microsoft.com/zh-cn/library/ms752253.aspx
Nullius

3
链接无效,教程在其他地方吗?
user1069816

只是花了一段时间试图弄清楚“管道已经结束”的原因。这里是我的解决上一个,希望能帮忙解决:stackoverflow.com/a/49075797/385273

62

试试这个。

这是服务部分。

[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文件那么灵活...
Alan S

9
很好,因为通常不希望通过app.config文件公开应用程序详细信息。
Frank Hileman 2014年

14
这是一个很好的示例,但是,永远不要仅使用net.pipe:// localhost /的基址。如果这样做,并且该计算机具有任何其他也使用net.pipe:// localhost /的程序,则ServiceHost在打开它时将引发异常。而是使用诸如net.pipe:// localhost / MyAppNameThatNobodyElseWillUse之类的独特名称。希望这有助于节省其他人的时间和沮丧!
道格·克洛特

此解决方案效果很好。特别是对于不需要在config中具有服务引用的内部端点。只需将合同(仅是接口定义)保留在它们自己的程序集中,也许将地址保留在config中即可。绑定改变的可能性很小。
Rob Von Nesselrode

2
我需要/helloservice在代理中添加到端点地址的末尾。
Mormegil '17

14

请查看我高度简化的Echo示例:它旨在使用基本的HTTP通信,但是可以通过编辑客户端和服务器的app.config文件,轻松地将其修改为使用命名管道。进行以下更改:

编辑服务器的app.config文件,删除或注释掉http baseAddress条目,并为命名管道(称为net.pipe)添加新的baseAddress条目。另外,如果您不打算将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条目。您还需要更改端点条目以使用管道:

<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以外,您还可以调整许多其他参数。


5
现在,链接已消失。
克里斯·韦伯

2

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

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服务的引用。


-2

我发现此站点非常有帮助,示例项目无需任何调整即可运行:https : //dotnet-experience.blogspot.com/2012/02/inter-process-duplex-communication-with.html

不要忘记在Windows功能中启用命名管道支持。本文在最佳答案中有一些效果不错的屏幕截图: 使用App.Config的Windows Service中的WCF命名管道

接受的解决方案中引用的项目无法在我的PC上按原样运行。我在app.config中尝试了一些修复程序,但仍然遇到以下异常:

System.InvalidOperationException:'服务'WpfWcfNamedPipeBinding.NamedPipeBindingService'具有零个应用程序端点(非基础结构)。这可能是因为没有为您的应用程序找到配置文件,或者是因为在配置文件中找不到与服务名称匹配的服务元素,或者是因为在服务元素中未定义端点。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.