C# WCF服务入门
之前在公司用的服务端是wcf写的,但是没有深入研究,最近找工作,面试的时候好多人看到这个总提问,这里做个复习
就用微软官方上的例子,搭一个简单的wcf服务,分6步
1 定义服务协定也就是契约,其实就是定义一个服务接口,这玩意后边是公开客户端用的,然后也告诉后边承载程序应该如何加载服务
主要涉及两个特性:一个是ServiceContract(接口的特性,定义这个是服务契约,里边又一些设置参数可以设置一下),OperationContract设置接口的方法的,如果不设置,方法就不会呗公开
这里是直接新建的wcf的服务程序,vs自动给生成了一个接口,就直接在这个里边添加了几个计算的接口函数了
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text; namespace GettingStartedLib
{ // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
//协定
[ServiceContract(//CallbackContract =typeof(ICallBack),//双工时的返回协定
ConfigurationName = "Calculator",//配置文件重的服务名
Name = "ICalculator",//webservice描述文件重的portType名
Namespace ="http://SampleWcfTest",//webservice描述文件重的portType命名空间
ProtectionLevel =System.Net.Security.ProtectionLevel.EncryptAndSign,//保护等级
SessionMode =SessionMode.Allowed)]//设置会话的支持模式
public interface ICalculator
{ [OperationContract]
string GetData(int value); [OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
//定义方法的操作,带了该特性才会被公布
[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); // TODO: 在此添加您的服务操作
}
public interface ICallBack
{
[OperationContract(IsOneWay = true)]
void Reply(string responseToGreeting);
} // 使用下面示例中说明的数据约定将复合类型添加到服务操作。
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello "; [DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
} [DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
2 实现上边的接口,vs自动生成了svc文件和对应的svc.cs文件,直接双击就是对应的实现类了,吧接口实现就好了,这个svc文件右键用文本编辑器打开可以进行编辑,如果后边用IIS加载的时候需要修改里边的东西
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text; namespace GettingStartedLib
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。
// 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。
public class Calculator : ICalculator
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
} public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
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;
}
}
}
3 承载服务,承载服务有几种方式,同时又设计到协议的绑定问题,
绑定分类:BasicHttpBinding 最基础的http绑定,
NetTcpbingding TCP的
NetNamePipeBinding IPC,也就是进程间通信,没用过。。
WSHttpBinding 这个是特殊的http/Https协议 加了其他东西的
NetMsmqBindiing,这个是消息队列,我没用过,这玩意好像需要额外装微软的消息队列才可以用
这里我基本就用wshttpbinding来实现,
承载方式:1)用控制台程序,直接用servicehost来承载服务,自己构造终结点:
//服务的地址
Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");
//承载服务的宿主
ServiceHost selfHost = new ServiceHost(typeof(Calculator), baseAddress); try
{
selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
selfHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("input<exit> to terminate service.");
Console.WriteLine();
while ("exit" == Console.ReadLine())
{
selfHost.Close();
}
}
catch (CommunicationException ex)
{
Console.WriteLine(ex.Message);
selfHost.Abort();
Console.ReadLine();
}
2) 用IIS承载,这里又两种方式,通过internet的方式 这个可以直接在vs中调试的,选中svc文件点调试会弹出一个wcf的客户端测试程序,可以直接进行测试,但是这个客户端不能测试异步,只能测同步
这中方式主要是需要配置一个web.config文件,部署的话,直接在IIS添加网站服务程序,把生成的DLL和web.config放在一个目录下应该跟这个调试是一样的(这种方式IIS5 6 只支持HTTP)
还可以通过WAS(进程激活服务,支持的协议比上边多,这个就没有深入研究了···)
<?xml version="1.0" encoding="utf-8"?>
<configuration> <appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<services>
<service name="GettingStartedLib.Calculator" behaviorConfiguration="MyServiceTypeBehaviors" >
<host>
<baseAddresses>
<add baseAddress="http://localhost:8001/"/>
</baseAddresses>
</host>
<endpoint address="CalculatorService" binding="wsHttpBinding" contract="Calculator">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!-- 将下列元素添加到服务行为配置中。 -->
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<!--<modules runAllManagedModulesForAllRequests="true"/>-->
<!--
若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
-->
<directoryBrowse enabled="true"/>
</system.webServer> </configuration>
3)通过windows服务程序承载,这个内部起始也是servicehost来实现,只不过是挂在windows服务程序上,需要自己实现一个windows服务,也就是继承servicebase类,重写onstart,在onstart中用servicehost加载服务,在stop中停止服务,同时需要配置文件就是程序的配置文件app.config记得生成到目录下,配置终结点。服务类生成的程序需要安装,还需要继承install实现一个安装类,把生成的服务程序安装到windows系统服务去,然后就可以在服务中启动服务,
这个安装是在管理员权限下进入对应的.netframework目录下运行installutil path(程序目录) 这里用的是4.5 ,就是v4.0。。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GettingStartedLib;
using System.ServiceModel.Description;
using System.ServiceModel;
using System.ServiceProcess;
using System.Configuration.Install;
using System.ComponentModel; namespace WcfConsole
{
public class serviceCalss : ServiceBase
{
public ServiceHost serviceHost = null;
public serviceCalss()
{
ServiceName = "WCFWindowsServiceSample"; }
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
serviceHost = new ServiceHost(typeof(Calculator)); serviceHost.Open();
} protected override void OnStop()
{
if (serviceHost != null)
{
serviceHost.Close();
serviceHost = null;
}
}
}
class Program
{
static void Main(string[] args)
{ ServiceBase.Run(new serviceCalss()); //服务的地址
Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");
//承载服务的宿主
ServiceHost selfHost = new ServiceHost(typeof(Calculator), baseAddress); //try
//{
// selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator");
// ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
// smb.HttpGetEnabled = true;
// selfHost.Description.Behaviors.Add(smb);
// selfHost.Open();
// Console.WriteLine("The service is ready.");
// Console.WriteLine("input<exit> to terminate service.");
// Console.WriteLine();
// while ("exit" == Console.ReadLine())
// {
// selfHost.Close();
// }
//}
//catch (CommunicationException ex)
//{
// Console.WriteLine(ex.Message);
// selfHost.Abort();
// Console.ReadLine();
//}
}
} [RunInstaller(true)]
public class ProjectInstaller : Installer
{
private ServiceProcessInstaller process;
private ServiceInstaller service; public ProjectInstaller()
{
process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
service = new ServiceInstaller();
service.ServiceName = "WCFWindowsServiceSample";
Installers.Add(process);
Installers.Add(service);
}
}
}
对应的配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<services>
<!-- This section is optional with the new configuration model
introduced in .NET Framework 4. -->
<service name="GettingStartedLib.Calculator"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
contract="Calculator" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
4 服务端承载好了,就可以用客户端调用服务了,又两种方式
客户端直接引用已经运行的服务,vs会自动生成一个对应的client类,里边又设置好的服务路径和接口之类的,也可以自己指定路径,只用他的函数,记得close
// CalculatorClient client = new CalculatorClient();
var client = myChannelFactory.CreateChannel(); double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
也可以用ChannelFactory<TChannel>类来构造一个client,这种模式是引用服务的契约接口,
var myBinding = new WSHttpBinding();
EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/GettingStarted/");
//EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/");
ChannelFactory<ICalculator> myChannelFactory = new ChannelFactory<ICalculator>(myBinding, myEndpoint);
这里边都可以用配置文件来设置终结点,也就是绑定类型和地址,配置方式与服务端类似
5,6就是配置和调用,这里就不说了
这里只是简单的wcf实例,
实际还有内容没有涉及:
1 不同的绑定类型,怎么选择,网上有个图是判断什么情况选择对应的绑定类型,其实就是选择协议
2 加密,因为之间的程序用的是basichttpbingding就是就是基本的http绑定,客户端没用引用服务端,服务端以web服务的形式公开服务,客户端直接以http请求的形式来与服务端通信,这样客户端cs和bs可以公用一个服务端,但是没有加密,传输的内容是完全公开的··讲道理web服务这玩意本来就是发过去给人看的·公开应该也没啥好像····,面试的时候问到这个问题直接懵逼了···这里暂时没写 ··这玩意好像挺麻烦的···
3 这里在4.5的环境下编写的,服务公开以后会自动生成对应的异步执行方法,与之前的方式不同,之前是老式的beginxxx的异步方式,返回一个Iasyncresult的结果,这里是4.5的async/await的形式来执行异步操作
4 wcf服务是可以兼容asp.net ,也可以返回json格式的对象··这个可以通过设置方法的操作特性可以设置
5 wcf服务支持双工,这个就很流弊了,不过讲道理tcp这种本身就支持双工,没具体研究
6 在双工模式下支持回调,这个意思好像是客户端请求完成再出发一个回调服务么··· 没研究···
。。。。。。
C# WCF服务入门的更多相关文章
- WCF入门教程(二)如何创建WCF服务
WCF入门教程(二)从零做起-创建WCF服务 通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) ...
- WCF入门教程(二)从零做起-创建WCF服务
通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) 定义了协议,具体什么操作,操作的参数和返回值 ...
- C#面向服务编程技术WCF从入门到实战演练
一.WCF课程介绍 1.1.Web Service会被WCF取代吗? 对于这个问题阿笨的回答是:两者在功能特性上却是有新旧之分,但是对于特定的系统,适合自己的就是最好的.不能哪一个技术框架和行业标准作 ...
- 跟我一起学WCF(12)——WCF中Rest服务入门
一.引言 要将Rest与.NET Framework 3.0配合使用,还需要构建基础架构的一些部件.在.NET Framework 3.5中,WCF在System.ServiceModel.Web组件 ...
- WCF入门(八)---WCF服务绑定
WCF服务绑定是一个集合,每个元素定义了服务与客户端进行通信方式的几个元素.传输元素和一个消息编码元素各自结合两个最重要的组成部分.这里是WCF服务绑定常用的列表. 基础绑定 基础约束是由basicH ...
- WCF入门(七)---自托管消费WCF服务
费自托管WCF服务的整个过程,一步步地解释以及充足的编码和屏幕截图是非常有必要. 第1步:服务托管,现在我们需要实现的代理类客户端.创建代理的方式不同. 使用svcutil.exe,我们可以创建代理类 ...
- WCF入门(六)---主机WCF服务
建立一个WCF服务后,下一步就是托管它,以便客户端应用程序可以使用,这就是所谓的WCF服务托管. WCF服务可以通过使用任何的四种方法如下托管. IIS主机 - IIS是Internet信息服务的缩写 ...
- WCF入门(五)---创建WCF服务
使用Microsoft Visual Studio2012创建WCF服务,理解如下所有必要的编码,更好地创建WCF服务的概念,这里做一个简单的任务. 启动Visual Studio 2012. 单击新 ...
- wcf第三方客户端与wcf服务之间调用入门
Wcf服务与我们的客户端如何建立联系的呢.本文简单记录一下 1.创建我们的wcf服务程序. 第一个wcf服务库是创建我们的wcf库,运行时会单独来托管我们的程序,而非托管在iis下. 第二个wcf服务 ...
随机推荐
- [ActionSprit 3.0] FMS远程共享
package { import flash.display.Sprite; import flash.events.NetStatusEvent; import flash.events.SyncE ...
- thinkphp3.2.3----图片上传并生成缩率图
public function uploadify(){ if(!IS_POST){ $this->error('非法!'); } $upload = $this->_upload(); ...
- EOFError: Compressed file ended before the end-of-stream marker was reached
EOFError: Compressed file ended before the end-of-stream marker was reached python在下载时,出现上述错误提示,一般这种 ...
- springboot项目,执行查询方法报错
org.hibernate.LazyInitializationException: could not initialize proxy [com.myproject.sell.dataobject ...
- JavaWeb后台从input表单获取文本值的两种方式
JavaWeb后台从input表单获取文本值的两种方式 #### index.html <!DOCTYPE html> <html lang="en"> & ...
- MVC返回数据流,ajax接受并保存文件
js代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...
- netty总结
eventLoopGroup中创建各个eventLoop处理线程,各个pipeLineHandler处理childEvent时是在自己的线程中, 全异步
- SpringBoot中使用Jackson导致Long型数据精度丢失问题
数据库中有一个bigint类型数据,对应java后台类型为Long型,在某个查询页面中碰到了问题:页面上显示的数据和数据库中的数据不一致.例如数据库中存储的是:1475797674679549851, ...
- es中的date类型
JSON中没有date类型,es中的date可以由下面3种方式表示: ①格式化的date字符串,例如"2018-01-01"或者"2018-01-01 12:00:00& ...
- uvm_cmdline_processor
无意中看到uvm_cmdline_processor,之前使用+UVM_TESTNAME也没深究,现在记录一下 内部调用脚本中的参数,通过使用uvm_cmdline_processor可以从脚本层级, ...