WCF中有很多种绑定,根据官方的说法,NetNamedPipeBinding是适用于同一台主机中不同进程之间的通信的。
今天终于实现了一个简单实例,整理一下。
1、服务端创建
首先要说一下,WCF服务是需要宿主程序的,可以寄宿在windows服务中、控制台中、桌面程序中……
看很多教程都是创建一个WCF项目,然后在创建一个其他项目去引用,实际摸索了一下,发现完全不用,直接在其他项目中去写相关代码即可。
依照个人喜好,我选择直接创建控制台项目。
例如:创建控制台项目【ConsolePipeWcf1】,添加【ConsoleServer1.cs】类 用于代码的方式配置服务,新建一个【Server1】的文件夹用于添加服务的接口和类:
ConsolePipeWcf1 ┳
┣Program.cs --程序主入口
┣ConsoleServer1.cs --用于配置服务
┗┳Server1
┣Server1.cs --接口的实现
┗IServer1.cs --接口的定义
首先,实现服务的主要内容
接口【IServer1.cs】:
using System.ServiceModel;
namespace ConsolePipeWcf1.Server1
{
[ServiceContract]
interface IServer1
{
[OperationContract]
string GetData(int value);
}
}
【Server1.cs】:
using System.Collections.Generic;
using System.ServiceModel;
namespace ConsolePipeWcf1.Server1
{
class Server1 : IServer1
{
public string GetData(int value)
{
//内容就敷衍一下吧
return string.Format("2 * value = {0}", 2 * value);
}
}
}
配置服务【ConsoleServer1.cs】:
(里面有些大括号只是为了代码好理解和方便查看加的)
using System;
using System.ServiceModel;
using ConsolePipeWcf1.Server1;
using System.ServiceModel.Description;
namespace ConsolePipeWcf1
{
//创建一个服务类
class ConsoleServer1
{
//基地址
private Uri baseAddress;
//终结点地址
public string address;
//服务主机实例
public ServiceHost serviceHost;
public ConsoleServer1()
{
baseAddress = new Uri("http://localhost:8010/console/server1/");
address = "net.pipe://localhost/console/server1/";
serviceHost = new ServiceHost(typeof(Server1.Server1), baseAddress);
}
public void CreatServer()
{
//NetNamedPipeBinding实例与配置
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);
{
binding.CloseTimeout = new TimeSpan(0, 1, 0);
binding.OpenTimeout = new TimeSpan(0, 1, 0);
binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
binding.SendTimeout = new TimeSpan(0, 1, 0);
binding.TransactionFlow = false;
binding.TransferMode = TransferMode.Buffered;
binding.TransactionProtocol = TransactionProtocol.OleTransactions;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MaxBufferPoolSize = 424288;
binding.MaxBufferSize = 65536;
binding.MaxConnections = 10;
binding.MaxReceivedMessageSize = 65536;
}
//Set Behavior
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = false;
smb.HttpsGetEnabled = false;
serviceHost.Description.Behaviors.Add(smb);
}
//Add Endpoint
{
//添加 mex终结点
serviceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex");
//添加NetNamedPipeBinding的终结点
serviceHost.AddServiceEndpoint(typeof(IServer1), binding, address);
}
}
//打开服务
public void OpenServer()
{
serviceHost.Open();
Console.WriteLine("The service1 is ready.");
}
//关闭服务
public void CloseServer()
{
serviceHost.Close();
Console.WriteLine("The service1 is closed.");
}
}
}
当然,以上代码也可以通过【App.Config】来实现,由于我的是控制台项目,默认的配置文件过于简单,可以新建个WCF项目把配置文件复制过来再改比较方便:
详见注释:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>省略</appSettings>
<system.web>省略</system.web>
<system.serviceModel>
<services>
<service name="ConsolePipeWcf1.Server1.Server1"><!--服务名要对!-->
<host>
<!--要有基地址-->
<baseAddresses>
<add baseAddress="http://localhost:8010/console/server1/" />
</baseAddresses>
</host>
<!--添加netNamedPipeBinding终结点-->
<endpoint address="net.pipe://localhost/console/server1/"
binding="netNamedPipeBinding"
contract="WCFNetNamedDemo.INnService">
</endpoint>
<!--mex终结点-->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<!--netNamedPipeBinding终结点设置-->
<netNamedPipeBinding>
<binding closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
transactionFlow="false"
transferMode="Buffered"
transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288"
maxBufferSize="65536"
maxConnections="10"
maxReceivedMessageSize="65536">
<security mode="Transport">
<transport protectionLevel="EncryptAndSign" />
</security>
</binding>
</netNamedPipeBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
最后就是宿主程序,也就是我的控制台主程序【Program.cs】:
using System;
namespace ConsolePipeWcf1
{
class Program
{
static void Main(string[] args)
{
//创建服务
ConsoleServer1 server1 = new ConsoleServer1();
server1.CreatServer();
//到开服务
server1.OpenServer();
//随便输入什么就关闭
Console.ReadLine();
server1.CloseServer();
}
}
}
完成以上,服务端就算完成。
2、客户端调用
新建控制台项目【ConsoleServer1Client】
把服务端的【IServer1.cs】接口文件(协议)复制过来,添加到项目中
然后:
using System;
//添加必要的引用
using System.ServiceModel;
//服务端IServer1的命名空间(由直接复制过来的IServer1.cs文件决定的)
using ConsolePipeWcf1.Server1;
namespace ConsoleServer1Client
{
class Program
{
static void Main(string[] args)
{
var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);
var address = new EndpointAddress("net.pipe://localhost/console/server1/");
//创建通道
var factory = new ChannelFactory<IServer1>(binding, address);
IServer1 channel = factory.CreateChannel();
//调用(因为有IServer1.cs文件,所以智能提示能提示出接口中的方法,不会报错)
string s = channel.GetData(5);//随便给个数
Console.WriteLine(s);
Console.ReadKey();
}
}
}
运行:
完成!
有点长了,下次说关于回调的实现,