之前在公司用的服务端是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. jquery源码解析:type,isPlainObject,parseHTML,parseXML,globalEval详解

    jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的. jQuery.extend({ ...... type: function( ...

  2. [转] 以普通用户启动的Vim如何保存需要root权限的文件

    [转] 以普通用户启动的Vim如何保存需要root权限的文件 在Linux上工作的朋友很可能遇到过这样一种情况,当你用Vim编辑完一个文件时,运行:wq保存退出,突然蹦出一个错误: E45: 'rea ...

  3. 8,Phaser__并发且多阶段任务

    使用场景 考选武状元 10 个 武生 参加考试 ,第一个关 靠耐力, 坚持最久的5个人进入第二关, 第二关考 力气,力气最大的 3个人进入第二关,第三关考兵法,兵法最好的当选武状元

  4. 【随记】SQL备份一张表的数据

    SQL Server: SELECT  *  INTO  table_bak   FROM   table Oracle.MySQL.SQLite: CREATE TABLE table_bak AS ...

  5. P4098 [HEOI2013]ALO 可持久化01Trie

    $ \color{#0066ff}{ 题目描述 }$ Welcome to ALO ( Arithmetic and Logistic Online).这是一个 VR MMORPG, 如名字所见,到处 ...

  6. P3267 [JLOI2016/SHOI2016]侦察守卫

    $ \color{#0066ff}{ 题目描述 }$ 小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的.换句话说,游戏的地图是一棵有N个节点的 ...

  7. 2016级算法第三次上机-C.AlvinZH的奇幻猜想——三次方

    905 AlvinZH的奇幻猜想--三次方 思路 中等题.题意简单,题目说得简单,把一个数分成多个立方数的和,问最小立方数个数. 脑子转得快的马上想到贪心,从最近的三次方数往下减,反正有1^3在最后撑 ...

  8. 编程开发之--Oracle数据库--存储过程使用动态参数绑定(3)

    1.动态参数绑定,可以实现动态的执行不同的sql --创建包 create or replace PACKAGE MYPACKAGE AS type empcursor is ref cursor; ...

  9. C#串口通讯中常用的16进制的字节转换

    1.对于通讯协议的十六进制数值进行简单转换 //二进制转十进制Console.WriteLine("二进制 111101 的十进制表示: "+Convert.ToInt32(&qu ...

  10. Java_方法的基本语法格式

    [修饰符] 返回值类型 方法名称([参数列表]){ 方法体 } [ ]中的内容是可有可无的 暂时将方法的修饰符编写为 public static 返回值类型有两种情况 : 第一种:无返回值类型,也就是 ...