「服务」WCF中NetNamedPipeBinding的应用实例
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
-
{
-
[
-
interface IServer1
-
{
-
[
-
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项目把配置文件复制过来再改比较方便:
详见注释:
-
-
<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();
-
}
-
}
-
}
运行:
完成!
原文地址: https://blog.csdn.net/Raink_LH/article/details/103721408
最后,如果用App.Config文件配置的话就不需要 CreatServer 这个方法了,
这种情况启动服务如下(因为配置server,endpoint 等信息已在App.Config文件):
static void Main(string[] args)
{
ServiceHost serviceHost = new ServiceHost(typeof(Services.CalculatorService));
//到开服务
serviceHost.Open();
Console.WriteLine("server start.......");
//随便输入什么就关闭
Console.ReadLine();
serviceHost.Close();
}