之前在公司用的服务端是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服务入门的更多相关文章

  1. WCF入门教程(二)如何创建WCF服务

    WCF入门教程(二)从零做起-创建WCF服务 通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) ...

  2. WCF入门教程(二)从零做起-创建WCF服务

    通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) 定义了协议,具体什么操作,操作的参数和返回值 ...

  3. C#面向服务编程技术WCF从入门到实战演练

    一.WCF课程介绍 1.1.Web Service会被WCF取代吗? 对于这个问题阿笨的回答是:两者在功能特性上却是有新旧之分,但是对于特定的系统,适合自己的就是最好的.不能哪一个技术框架和行业标准作 ...

  4. 跟我一起学WCF(12)——WCF中Rest服务入门

    一.引言 要将Rest与.NET Framework 3.0配合使用,还需要构建基础架构的一些部件.在.NET Framework 3.5中,WCF在System.ServiceModel.Web组件 ...

  5. WCF入门(八)---WCF服务绑定

    WCF服务绑定是一个集合,每个元素定义了服务与客户端进行通信方式的几个元素.传输元素和一个消息编码元素各自结合两个最重要的组成部分.这里是WCF服务绑定常用的列表. 基础绑定 基础约束是由basicH ...

  6. WCF入门(七)---自托管消费WCF服务

    费自托管WCF服务的整个过程,一步步地解释以及充足的编码和屏幕截图是非常有必要. 第1步:服务托管,现在我们需要实现的代理类客户端.创建代理的方式不同. 使用svcutil.exe,我们可以创建代理类 ...

  7. WCF入门(六)---主机WCF服务

    建立一个WCF服务后,下一步就是托管它,以便客户端应用程序可以使用,这就是所谓的WCF服务托管. WCF服务可以通过使用任何的四种方法如下托管. IIS主机 - IIS是Internet信息服务的缩写 ...

  8. WCF入门(五)---创建WCF服务

    使用Microsoft Visual Studio2012创建WCF服务,理解如下所有必要的编码,更好地创建WCF服务的概念,这里做一个简单的任务. 启动Visual Studio 2012. 单击新 ...

  9. wcf第三方客户端与wcf服务之间调用入门

    Wcf服务与我们的客户端如何建立联系的呢.本文简单记录一下 1.创建我们的wcf服务程序. 第一个wcf服务库是创建我们的wcf库,运行时会单独来托管我们的程序,而非托管在iis下. 第二个wcf服务 ...

随机推荐

  1. [AIR] 与本地进程(应用程序)进行通讯

    毫不夸张的说,此功能可以将Windows命令行程序(cmd.exe)通过AIR应用封装起来,并指挥它做任何你想做的事情 AIR2.0及以上与本地进程的交互主要体现在以下几方面: 启动进程并提供初始参数 ...

  2. ArchLinux下shadow服务报错

    用着Linux蓦然开机就报错了.我是个对报错很敏感的,而是是开机报错. 这个的严重性,听一位前辈说过:如果开机报错你都不理它,慢慢的它就会宕机. 报错内容: shadow服务是Linux下用于校队pa ...

  3. Windows下Jmeter安装出现Not able to find Java executable or version问题解决方案

    安装好java1.8.jmeter4.0,并java -version正常,jmeter也能正常使用.某一次使用突然出现Not able to find Java executable or vers ...

  4. screen新建窗口,环境变量跟原来不一致。

    昨天为了方便npm安装全局包,我把环境变量重新配置了. 然后,在项目中引用全局包没有出问题.但是后来我在screen里面引用全局包,报错说找不到. 使用#npm list -g命令 发现昨天的全局包都 ...

  5. 条目二十三《考虑用排序的vector替代关联容器》

    条目二十三<考虑用排序的vector替代关联容器> 在看到这个条目的标题的时候,说实话,我一下子是比较懵逼的.这个结论怎么和数据结构的时间复杂度不一致了? 一般来说,像map,set等关联 ...

  6. 1. java 的访问修饰符

    一.什么情况下使用修饰符 属性通常使用private封装起来 方法一般使用public用于被调用 会被子类继承的方法,通常使用protected private protected package p ...

  7. elasticsearch kibana简单查询

    kibana CRUD 操作页面 一.简单的CRUD操作 1.添加 PUT /index/type/id {  "json数据" } 2.查询 GET /index/type/id ...

  8. 基于MODBUS的CRC

    %ws   WCHAR wszName CRC原理 设编码前的原始信息多项式为P(x),P(x)的最高幂次加1等于k:生成多项式为G(x),G(x)的最高幂次等于r:CRC多项式为R(x):编码后的带 ...

  9. 矩阵&&高斯消元

    矩阵运算: \(A\times B\)叫做\(A\)左乘\(B\),或者\(B\)右乘\(A\). 行列式性质: \(1.\)交换矩阵的两行(列),行列式取相反数. \(2.\)某一行元素都\(\ti ...

  10. jenkins+Publish Over SSH 提示:Transferred 0 file(s)

    之前公司用jekins来进行自动化发布,现在公司因没有运维,所以自己学习.并搭建了一个jenkins的环境来进行项目自动化部署. 不料在最后连接ssh后部署时,一直提示Transferred 0 fi ...