初识.net WCF
WCF, Windows Communication Foundation 是.net一个基于服务的通信框架。
我所理解的基于服务,是指采用客户端-服务端模式提供的服务。
WCF的前身应该是web service,WCF作为继承者,除了web service的功能外,提供了更多的配置选项。
服务端与客户端之间的交互,不仅仅是HTTP,可以是其他的通信机制,比如MSMQ。
与web service类似,WCF的创建,也比较依赖vs工具进行搭建,自己做不是说做不了,而是麻烦很多。
在这里简单记录一个WCF服务端和客户端的例子。
服务端
WCF服务端提供各种功能供客户端调用/通信。
wcf服务端分为两部分,服务内容,和宿主。
WCF服务提供内容简单认为有ABC
三部分,即
- A, Address,服务提供地址
- B, Binding, 服务提供的的协议
- C, Contract,服务内容格式
服务内容
web service的服务,一般来说是一个标记有WebServiceAttribute
的类;
而WCF的服务,是一个带有ServiceContractAttribute
接口的类库,这也就是所谓的C-Contract
,它定义的是服务应用侧的数据格式,服务接口。
接口对应的实现,则没有特殊的标记。
接口
这里是用的MS官网上的WCF服务作为例子
[ServiceContract]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
}
实现
接口的实现没有特别的属性注释,正常实现接口即可
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
// Code added to write output to the console window.
Console.WriteLine("Return: {0}", result);
return result;
}
public double Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
}
配置
对应的wcf在配置文件app.config
中的配置。
这里指定了上面提到的ABC
,不过在容器中,同样也需要进行相同的配置。
<system.serviceModel>
<services>
<service name="GettingStartedLib.CalculatorService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:18000/GettingStarted/CalculatorService" />
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="GettingStartedLib.ICalculator">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
宿主
宿主
Web应用或者Console应用都可以作为宿主,这里以控制台应用为例。
private static void Main(string[] args)
{ // Step 1 Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://localhost:60002/GettingStarted/");
// Step 2 Create a ServiceHost instance
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);
try
{
// Step 3 Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
// Step 4 Enable metadata exchange.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
// Step 5 Start 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();
}
}
- 创建一个
Uri
,这个地址就是这个服务的基础地址 - 创建一个SelfHost,绑定到该地址上,则该服务在该地址上运行
- 创建一个
endpoint
,endpoint
是服务的触点,个人把他理解为例如网站中网页的地址,真正用于交互的是endpoint
。endpoint
指明了该服务提供的具体服务类型ICalculator
(从而了解该服务包含哪些方法),服务的通信协议、又叫binding
,服务的访问地址CalculatorService
,该地址叠加在基地址Uri
上。 - 增加
behaviour
。behaviour
定义了服务提供的一些功能,再实例中提使能了metatdata
的获取 - 启动宿主机
启动后,就能在指定地址http://localhost:60002/GettingStarted/
该服务了。
不过为了通过程序访问,还需要搭建客户端
客户端
WCCF的客户端搭建,依赖vs自带的功能,或者使用微软的svcutil.exe
工具。
- 新建一个console应用
- 增加
System.ServiceModel
引用 - 在Solution窗口中,右键点击该项目,在弹出菜单中选择
Add->Service Reference
- 在弹出窗口中的地址中,输入服务端的地址,点击
Go
开始解析 - 解析完毕,可以看到刚刚建立的
CalculatorService
服务endpoint
,点击OK
即可引入该服务 - 引入服务后,就可以像本地调用一样,创建该服务实力,调用服务方法了。方法内部包含了实际的远程调用过程,不过这些对调用者是透明的。
private static void Main(string[] args)
{
//Step 1: Create an instance of the WCF proxy.
CalculatorClient client = new CalculatorClient();
// Step 2: Call the service operations.
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation.
value1 = 145.00D;
value2 = 76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
// Call the Multiply service operation.
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
//Step 3: Closing the client gracefully closes the connection and cleans up resources.
client.Close();
Console.ReadLine();
}
总结
简单的使用WCF与web service类似,但是WCF包含了很多高级功能,如异步、跨平台、多种通信方式、安全认证等等,这些是WCF强大的地方。