在VS2010里建立一个最简单的WCF的Demo
先介绍一些基本概念:
1.体系中的角色。
在WCF的结构中,至少应该有两个角色:服务端和客户端。服务端公开一个或多个服务,客户端访问这些服务以获得相应的逻辑。WCF的服务必须有宿主,随宿主一起启动后,客户端才可以访问到(本文就将WCF服务寄宿到Console程序中)。
2.服务(Service)和操作(Operation)
3. 终结点(EndPoint)服务端公开了一个或多个服务(通俗点讲就是接口),每个服务都拥有一个或多个操作(接口方法),客户端通过调用服务的操作来获得服务提供的逻辑。所有标记为 [ServiceContract] 属性(需添加System.ServiceModel引用)的接口都表示该接口是一个服务协定,所有标记为 [OperationContract] 属性的方法都表示该方法是一个操作协定,服务协定和操作协定是可以被客户端调用到的,没有这些标记的接口和方法,服务端本地当然还可以用,但是客户端就访问不到了。
终结点包括三个组成部分,即”A","B","C"
A(Address):英文理解为"地址",在计算机中是通过一个URI唯一地址标识,通过这个地址我们可以找到我们要调用的WCF服务。
A解决了:Where to locate the WCF Service?
B(Binding):英文理解为"捆绑,绑定", Binding实现在Client和Service通信的所有底层细节。如:我们在客户端与服务端传输的时候采用的是什么样的编码,XML?Text?二进制?...采用哪种传输协议进行传输,TCP?Http?以及采用什么样的机制解决安全问题,SSL?加密?...
B解决了:How to communicate with service?
C(Contract):英文理解为"合同",合同是什么?告诉我们哪些事能做,如些事不能做。 Contract的主要的作用是暴露某个WCF Service所提供的所有有效的方法。Contract实际上是把每个方法的转化成为相对应的消息。
4.元数据(Metadata)
C解决了:What functionalities do the Service provide?
服务端现在服务端公开了服务,客户端循着正确的终结点,持着正确的绑定找到了服务端,此时服务端笑而不语,客户端不知所措,因为客户端根本不知道服务端公布了那些服务、操作、数据。客户端一个调用也写不出来。虽然客户端不需知道服务和操作的具体实现细节,但是它必须知道服务的接口描述(或类型描述)、操作的方法签名,数据的类描述,这些描述就叫做元数据,服务端必须通过某种方法把元数据交给客户端,这种方法叫做元数据交换(Metadata Exchange)。
一:新建控制台应用程序,命名WcfDemo
二:在Program.cs中创建服务协定和实现服务协定
[ServiceContract]
public interface IService
{
[OperationContract]
string GetMessage();
}
public class Service1 : IService
{
public string GetMessage()
{
string address = OperationContext.Current.Channel.LocalAddress.ToString();
return string.Format("来自 Service1,地址:{0}", address);
}
}
public class Service2 : IService
{
public string GetMessage()
{
string address = OperationContext.Current.Channel.LocalAddress.ToString();
return string.Format("From Service2,Address:{0}", address);
}
}
三:添加App.config,修改配置信息
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<!--name="命名空间.服务实现类名" behaviorConfiguration=下面behavior的name,或者同时省略-->
<service name="WcfDemo.Service1" behaviorConfiguration="WcfBehavior">
<host>
<baseAddresses>
<!--可以写多个baseAddress,但每种传输协议只能定义一个baseAddress。HTTP的baseAddress同时是service对外发布服务说明页面的URL-->
<add baseAddress="http://localhost:9999/WcfDemo/Service1"/>
<add baseAddress="net.tcp://localhost:8888/WcfDemo/Service1"/>
</baseAddresses>
</host>
<!--address不可重复,包括不可以有两个为空
address可以为空,则服务地址为baseAddress
address可以为相对地址,则服务地址为baseAddress+address,
address可以为绝对地址,则服务地址为address
binding有很多种,wsHttpBinding是基于http协议的,netTcpBinding,mexTcpBinding是基于tcp协议的,其他的待学习
contract="命名空间.服务接口类名"-->
<!--多个终结点就表示有多个路径可以指向服务地址,条条大路通罗马的意思
但是在客户端创建Client类时,必须指定endpointConfigurationName-->
<endpoint address="Service_CH1" binding="wsHttpBinding" contract="WcfDemo.IService"/>
<endpoint address="Service_CH2" binding="netTcpBinding" contract="WcfDemo.IService"/>
<!--每个终结点对应相应的协议,若没有此终结点,则在添加服务引用的时候搜不到,这里不能用netTcpBinding-->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
<service name="WcfDemo.Service2" behaviorConfiguration="WcfBehavior">
<host>
<baseAddresses>
<!--因为寄宿于同一个程序,所以相同的传输协议,端口可以共用-->
<add baseAddress="http://localhost:9999/WcfDemo/Service2"/>
<add baseAddress="net.tcp://localhost:8888/WcfDemo/Service2"/>
</baseAddresses>
</host>
<endpoint address="Service_EN1" binding="wsHttpBinding" contract="WcfDemo.IService"/>
<endpoint address="Service_EN2" binding="mexTcpBinding" contract="WcfDemo.IService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfBehavior">
<serviceMetadata httpGetEnabled="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
四:修改Main方法
static void Main(string[] args)
{
try
{
ServiceHost host1 = new ServiceHost(typeof(Service1));
host1.Open();
ServiceHost host2 = new ServiceHost(typeof(Service2));
host2.Open();
}
catch (Exception)
{
throw;
}
Console.WriteLine("服务已开启");
Console.ReadKey();
}
四:编译项目,运行(注意需用管理员身份运行)
可在浏览器输入wcf服务地址:http://localhost:9999/WcfDemo/Service1
说明服务启动成功。
客户端
一:新建控制台应用程序,命名WcfClient
二:右键“引用”,选择“添加服务引用”
地址栏可以输入http://localhost:9999/WcfDemo/Service1,net.tcp://localhost:8888/WcfDemo/Service1中的任何一个,指向同一个WCF服务。然后更改命名空间WcfSvc1,点击确定。
因为有两个Service,再添加一个WcfSvc2。
三:添加服务引用后,自动生成配置文件app.config,生成四个endpoint,分别对应客户端的四个endpoint
<client>
<endpoint address="http://localhost:9999/WcfDemo/Service1/Service_CH1"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService"
contract="WcfSvc1.IService" name="WSHttpBinding_IService">
<identity>
<userPrincipalName value="***" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:8888/WcfDemo/Service1/Service_CH2"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IService"
contract="WcfSvc1.IService" name="NetTcpBinding_IService">
<identity>
<userPrincipalName value="***" />
</identity>
</endpoint>
<endpoint address="http://localhost:9999/WcfDemo/Service2/Service_EN1"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
contract="WcfSvc2.IService" name="WSHttpBinding_IService1">
<identity>
<userPrincipalName value="***" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:8888/WcfDemo/Service2/Service_EN2"
binding="netTcpBinding" bindingConfiguration="MetadataExchangeTcpBinding_IService"
contract="WcfSvc2.IService" name="MetadataExchangeTcpBinding_IService" />
</client>
四:修改Main方法
static void Main(string[] args)
{
WcfSvc1.ServiceClient client11 = new WcfSvc1.ServiceClient("WSHttpBinding_IService");
Console.WriteLine(client11.GetMessage());
WcfSvc1.ServiceClient client12 = new WcfSvc1.ServiceClient("NetTcpBinding_IService");
Console.WriteLine(client12.GetMessage());
WcfSvc2.ServiceClient client21 = new WcfSvc2.ServiceClient("WSHttpBinding_IService1");
Console.WriteLine(client21.GetMessage());
WcfSvc2.ServiceClient client22 = new WcfSvc2.ServiceClient("MetadataExchangeTcpBinding_IService");
Console.WriteLine(client22.GetMessage());
Console.Read();
}
因为一个WCF服务有两个endpoint,所以实例化Client时需指定endpoint的name;若只有一个endpoint,则实例化时可省去此参数。
五:运行程序
至此,WCF程序完成。
参考博文:
1.宋业飞的专栏,老老实实学习WCF
http://blog.csdn.net/songyefei/article/details/7363296
2.Lullaby's Blog,WCF学习总结
http://blog.csdn.net/fangxing80/article/details/6106228