WCF 命名管道最小示例

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

微软有一篇精彩的文章 入门教程,它通过 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();
}

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

111986 次浏览

I just found this excellent little tutorial. broken link (Cached version)

I also followed Microsoft's tutorial which is nice, but I only needed pipes as well.

As you can see, you don't need configuration files and all that messy stuff.

By the way, he uses both HTTP and pipes. Just remove all code lines related to HTTP, and you'll get a pure pipe example.

Try this.

Here is the service part.

[ServiceContract]
public interface IService
{
[OperationContract]
void  HelloWorld();
}


public class Service : IService
{
public void HelloWorld()
{
//Hello World
}
}

Here is the Proxy

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

And here is the service hosting part.

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

Check out my highly simplified Echo example: It is designed to use basic HTTP communication, but it can easily be modified to use named pipes by editing the app.config files for the client and server. Make the following changes:

Edit the server's app.config file, removing or commenting out the http baseAddress entry and adding a new baseAddress entry for the named pipe (called net.pipe). Also, if you don't intend on using HTTP for a communication protocol, make sure the serviceMetadata and serviceDebug is either commented out or deleted:

<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>

Edit the client's app.config file so that the basicHttpBinding is either commented out or deleted and a netNamedPipeBinding entry is added. You will also need to change the endpoint entry to use the pipe:

<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>

The above example will only run with named pipes, but nothing is stopping you from using multiple protocols to run your service. AFAIK, you should be able to have a server run a service using both named pipes and HTTP (as well as other protocols).

Also, the binding in the client's app.config file is highly simplified. There are many different parameters you can adjust, aside from just specifying the baseAddress...

I created this simple example from different search results on the internet.

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

Using the above URI I can add a reference in my client to the web service.