zoukankan      html  css  js  c++  java
  • Wcf

    1

    分成Wcf服务库 和wcf服务应用程序


    [ServiceContract] //1.0 标注当前接口为wcf的服务
    public interface IService1
    {
    [OperationContract]//2.0 标注此方法是一个WCF的服务方法,可以被外部调用
    string GetData(int value);

    [OperationContract]
    CompositeType GetDataUsingDataContract(CompositeType composite);

    // TODO: 在此添加您的服务操作
    }

    2 配置文件(这是wcf类库)

    <system.serviceModel>

    <!-------------------1-->
    <services>
    <!--3.0service这个节点中的名称必须是服务契约的实现类的完全限定名称 -->命名空间+类名
    <service name="WCFLib.Service1">
    <host>
    <baseAddresses>
    <!--4.0 baseAddress表示wcf主机监听的具体url,本质上是被socket来监听的-->
    <add baseAddress = "http://localhost:8733/Design_Time_Addresses/WCFLib/Service1/" />
    </baseAddresses>
    </host>
    <!-- Service Endpoints -->
    <!-- 除非完全限定,否则地址将与上面提供的基址相关,如果address为空则默认使用baseAddress -->
    <!--5.0 contract一定要指定当前服务的接口的完全限定名称-->
    <endpoint address="" binding="basicHttpBinding" contract="WCFLib.IService1">
    <!--
    部署时,应删除或替换下列标识元素,以反映
    用来运行所部署服务的标识。删除之后,WCF 将
    自动推断相应标识。
    -->
    <identity>
    <dns value="localhost"/>
    </identity>
    </endpoint>
    <!-- Metadata Endpoints -->
    <!-- 元数据交换终结点供相应的服务用于向客户端做自我介绍。 -->
    <!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除-->
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
    <!----------------------1-->



    <!----------------------2-->

    <service name="WCFLib.BizOrder">
    <host>
    <baseAddresses>
    <add baseAddress="http://localhost:8733/Design_Time_Addresses/WCFLib/BizOrder/"/>
    </baseAddresses>
    </host>
    <endpoint address="" binding="basicHttpBinding" contract="WCFLib.IOrder"></endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>


    <!---------------------2-->


    ---------------------33333333333
    <!--用于约定WCF的统一行为-->(全局设置) 但是 局部大于全局
    <behaviors>
    <serviceBehaviors>
    <behavior>
    <!-- 为避免泄漏元数据信息,
    请在部署前将以下值设置为 false -->
    <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
    <!-- 要接收故障异常详细信息以进行调试,
    请将以下值设置为 true。在部署前设置为 false
    以避免泄漏异常信息-->
    <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
    </serviceBehaviors>
    </behaviors>


    ---------------------------------3----------
    </system.serviceModel>


    3 wcf 应用程序 IIS托管 端口是随机分配的 所有没有<host> 节点
    在客户端添加的时候 用2种方法可以添加
    3.1 直接添加服务引用 这种简单(vs帮你操作)

    3.2 手动调用(纯手工)

    工具--》外部工具--》添加----

    命令: C:Program Files (x86)Microsoft SDKsWindowsv7.0ABinSvcUtil.exe
    初始目录 : 选择项目目录
    勾选 使用输出窗口 提示输入参数

    生成后 ---》点击客户端 --在点击工具 --》在输入的参数中 输入 服务在浏览器中显示的路径---》生成2个文件 (outputConfig 和
    Service1)

    将outputConfig 文件配置中的 <system.serviceModel> </system.serviceModel>节点配置添加到配置文件中就可以删除outputConfig 了


    在生成的Sercice1中 需要添加2个命名空间
    System.ServiceModel
    System.Runtime.Serialization



    调用
    Service1Client c = new Service1Client();
    MessageBox.Show(c.GetData(100));



    3.3 如果还需要添加服务的话 就添加一个 wcf 服务 比如是Order服务(自动生成2个文件 1个是 Iorder 1个是 Order.svc)

    在Iorder 中定义一个方法
    【operationContract】
    string DoWork()


    Order.svc:Iorder 中需要实现这个方法

    public string DoWork()
    {
    return "sadasdas";
    }

    浏览Order.svc开始服务

    根据工具 --添加生成代理类的时候还是会生成上面的outputconfig 和 Order.cs 文件


    注意了此时你要将outputconfig 的配置文件迁移到项目的配置文件中可能是 (webconfig 也有可能是 appconfig )

    前面已经添加了一个服务 配置 所有你不能全部复制 <system.serviceModel> </system.serviceModel>节点的

    选择outputconfig 中
    《basicHttpBinding》
    <binding>就是这个节点需要复制上面的节点不管<binding/>(复制这个节点 到项目配置文件中)
    </basicHttpBinding>


    选择
    《Cline》
    <ednpoin/>(选择这个节点添加到)-----跟目录下的Client下面
    《/Client》


    4 wcf 服务类库的自托管代码演示
    public class 服务托管类
    {
    static void Main()
    {
    //1.0 利用代码 自托管WCF服务
    /*
    * ServiceHost第一个参数:表示要托管的 wcf服务的实现类的Type类型
    * 第二个参数:baseAddress表示当前wcf服务监听的url,如果没有填写默认去app.config中查找
    */
    using (ServiceHost host = new ServiceHost(typeof(Service1)))
    {
    //开启主机环境
    host.Open();

    Console.WriteLine("wcf服务Services1已经启动....");

    Console.ReadKey();
    }
    }
    }

    5 Wcf 数据方法
    5.1 请求响应方法
    ServiceReference1.Service1Client c = new ServiceReference1.Service1Client();
    MessageBox.Show(c.GetData(300));响应完了才返回

    5.2 数据报方法

    数据报方法 (IsOneWay = true 方法的返回类型必须是void
    在接口中定义
    /// <summary>
    /// //标记了此方法是一个数据报访问,特点是,客户端调用此方法后马上响应回去,不管此方法要执行多久
    /// </summary>
    /// <param name="logtxt"></param>
    [OperationContract(IsOneWay = true)]
    void WriteLog(string logtxt);

    在实现类中 (Iservice中)
    public void WriteLog(string logtxt)
    {
    //写日志到数据库或者磁盘上 (很耗时间)
    System.Threading.Thread.Sleep(5000);
    }


    6 Wcf的双工通讯

    6.1 添加一个wcf类库
    添加一个接口
    /// <summary>
    /// 1.0 将接口标记成一个双工通讯接口
    /// </summary>
    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IResult))]
    public interface ILogger
    {
    /// <summary>
    /// 3.0 此方法也必须是一个数据报的方法
    /// </summary>
    /// <param name="logtxt"></param>
    [OperationContract(IsOneWay = true)]
    void WriteLog(string logtxt);
    }

    /// <summary>
    /// 2.0 接口的名称可以由程序员自行定义
    /// </summary>
    public interface IResult
    {
    /// <summary>
    /// 2.0.1 特点:此方法必须是一个数据报的方法
    /// </summary>
    /// <param name="msg"></param>
    [OperationContract(IsOneWay = true)]
    void WriteResult(string msg);
    }

    6.2 添加实现接口

    public class Logger : ILogger
    {
    IResult iresult;
    /// 4.0 <summary>
    /// 构造函数中接收在客户端实现了IResult的子类的对象实例
    /// </summary>
    public Logger()
    {
    //获取了客户端的IResult的具体实现类的对象实例
    iresult = OperationContext.Current.GetCallbackChannel<IResult>();
    }

    public void WriteLog(string logtxt)
    {
    //1.0 接收到数据以后需要5秒钟才能处理完成
    System.Threading.Thread.Sleep(5000);

    //2.0 通过回调客户端的函数将处理结果响应给客户端
    iresult.WriteResult("您的请求已经处理成功,耗时5秒钟");
    }
    }


    在客户端调用的时候
    添加服务引用
    配置文件中有变化了
    <system.serviceModel>
    <bindings>
    <wsDualHttpBinding>
    <binding name="WSDualHttpBinding_ILogger" closeTimeout="00:01:00"
    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
    <reliableSession ordered="true" inactivityTimeout="00:10:00" />
    <security mode="Message">
    <message clientCredentialType="Windows" negotiateServiceCredential="true"
    algorithmSuite="Default" />
    </security>
    </binding>
    </wsDualHttpBinding>
    </bindings>
    <client>
    <endpoint address="http://localhost:8733/Design_Time_Addresses/WCF%E5%8F%8C%E5%B7%A5/Logger/"
    binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_ILogger"
    contract="ILogger" name="WSDualHttpBinding_ILogger">
    <identity>
    <userPrincipalName value="ivanybivan" />
    </identity>
    </endpoint>
    </client>
    </system.serviceModel>

    、、 在生成代理类的时候 wcf服务类库中的接口ILogger 变成了ILoggerCallback 可以在代理类中查看
    public class ResultProcessor : ILoggerCallback
    {
    public void WriteResult(string msg)
    {
    MessageBox.Show(msg);
    }
    }

    private void button1_Click(object sender, EventArgs e)
    {
    // 传一个实现了接口的实咧
    LoggerClient c = new LoggerClient(new System.ServiceModel.InstanceContext(new ResultProcessor()));

    c.WriteLog("这是异常信息");
    }

    7 Wcf 如果想建个服务开启电脑就可以运行 那么久可以建个 window服务


    8 IIS 承载Net.tcp
    1 新建一个wcf服务应用程序 WcfNetTcp
    2 新建一个WcfLib服务类库WCFLib; 在新建的服务类库中的配置文件中 去掉《host》</host>节点
    修改终结点 endpoint节点
    address="net.tcp://127.0.0.1/wcfNetTcp2323/Service1.svc" (指向服务应用程序,,wcfNetTcp2323名而已)

    binding 的修改方式 : 点击AppConfig右键复制路径---》工具--》wcf服务配置编辑器--》文件--》打开--》配置文件-》 粘贴路径
    就打开了wcf相关绑定配置数据--》服务 --》终结点 --》点击第一个空名称 然后选择 netTcpBinding
    --》点击文件--》保存 就保存了这次的选择绑定

    3 wcfLIb服务类库不能承载在iis上面 所以我们用Wcf服务应用程序来承载

    删除WcfNetTcp的契约IService 和 Svc下面的实现类 --》添加WcfLib的引用--修改WcfNetTcp的Service1.svc中
    Service="WcfLib.Service1"指向类库的实现类) 并删除CodeBehind="Service1.svc.cs"

    4 将服务类库WcfLib中的配置文件迁移到WcfNetTcp服务应用程序中的配置文件中
    <services>
    <service name="WcfLib.Service1">
    <endpoint address="net.tcp://127.0.0.1/wcfNetTcp/Service1.svc"
    binding="netTcpBinding" bindingConfiguration="" contract="WcfLib.IService1">
    <identity>
    <dns value="localhost" />
    </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
    </services>

    5 打开IIS 在默认的网站中--》右击浏览(找到所在的物理文件)---》新建一个文件夹 netTcp--》拷贝路径--》

    6 选择vs中的WcfNetTcp程序--》右击发布--》新建一个配置--》使用文件系统--》
    在目标位置输入 刚才拷贝的iis路径 D:Net Tcp et Tcp

    7 发布成功后 在默认网站上 --右击--》添加应用程序--》
    别名 一定要和 address="net.tcp://127.0.0.1/WcfByNetTCp/Service1.svc" 中的WcfByNetTCp 这个一一模一样
    别名: WcfByNetTCp
    物理路径 : D:Net Tcp et Tcp

    8 此时建立的是Http
    点击新建的那个默认网站 --》右击--》管理网站--》高级设置--在已启用的协议中 改成 http,net.tcp

    9 点击该运用程序--》右击--》管理网站--》高级设置--在已启用的协议中 改成 http,net.tcp

    10 点击默认网站--》绑定--添加--》类型改成nettcp--》默认信息 808:*


    11 控制面板--》程序功能--》打卡或者关闭Window功能 --》在。netFrameWork中http 和非http都选上

    12 点击应用程序--》管理应用程序--》浏览 --》点击Service.Svn -->复制路径

    13 新建一个客户端调用的 --.添加服务应用 --》 后面的都一样了


    9 WcF 事物的用法
    契约和实现类写在yiq
    using System.Data.SqlClient;
    using System.ServiceModel;
    [ServiceContract(SessionMode = SessionMode.Required)] //1 设置当前契约的session模式为开启会话绑定
    public interface IPig
    {
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    void AddDog();
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    void AddPig();
    }

    /// <summary>
    /// 特性说明
    /// 1 //定义当前的事物隔离级别为序列化流
    /// 2 // 是否自动提交当前session中所有的事物方法
    /// 3 //完成操作以后是否释放对象
    /// </summary>
    [ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable
    , TransactionAutoCompleteOnSessionClose = true
    , ReleaseServiceInstanceOnTransactionComplete = true
    )]
    public class Pig : IPig
    {
    // TransactionScopeRequired=true:当前的方法在客户端调用的时候必须要存放在TransactionScope中
    //TransactionAutoComplete = true :自动提交事物
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void AddDog()
    {
    Insert("dog", "DB1");
    }

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void AddPig()
    {
    throw new Exception("errror");
    Insert("Pig", "DB2");
    }

    void Insert(string context, string dbname)
    {
    using (SqlConnection conn = new SqlConnection("server=.;database=" + dbname + ";uid=sa;pwd=master;"))
    {
    conn.Open();
    string sql = "insert into TableA(context) values('" + context + "')";
    SqlCommand command = new SqlCommand(sql, conn);
    command.ExecuteNonQuery();
    }
    }
    }

    配置文件
    <system.serviceModel>
    <services>
    <service name="TransLib.Pig">
    <host>
    <baseAddresses>
    <add baseAddress = "http://localhost:8733/Design_Time_Addresses/TransLib/IPig/" />
    </baseAddresses>
    </host>
    <!-- Service Endpoints -->
    <!-- 除非完全限定,否则地址将与上面提供的基址相关 -->
    <endpoint address="" binding="wsHttpBinding" contract="TransLib.IPig" bindingConfiguration="trans">
    <!--
    部署时,应删除或替换下列标识元素,以反映
    用来运行所部署服务的标识。删除之后,WCF 将
    自动推断相应标识。
    -->
    <identity>
    <dns value="localhost"/>
    </identity>
    </endpoint>
    <!-- Metadata Endpoints -->
    <!-- 元数据交换终结点供相应的服务用于向客户端做自我介绍。 -->
    <!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除 -->
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
    </services>
    <behaviors>
    <serviceBehaviors>
    <behavior>
    <!-- 为避免泄漏元数据信息,
    请在部署前将以下值设置为 false -->
    <serviceMetadata httpGetEnabled="True"/>
    <!-- 要接收故障异常详细信息以进行调试,
    请将以下值设置为 true。在部署前设置为 false
    以避免泄漏异常信息 -->
    <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
    </serviceBehaviors>
    </behaviors>
    <bindings>
    <wsHttpBinding>
    <binding name="trans" transactionFlow="True"></binding>
    </wsHttpBinding>
    </bindings>
    </system.serviceModel>


    在客户端调用的时候
    public static void Main()
    {
    ServiceReference1.PigClient c = new ServiceReference1.PigClient();
    using (System.Transactions.TransactionScope scop = new System.Transactions.TransactionScope())
    {
    try
    {
    c.AddDog();
    c.AddPig();

    scop.Complete();
    }
    catch
    {

    }
    }

    Console.WriteLine("执行成功");
    Console.ReadKey();
    }


  • 相关阅读:
    Android(java)学习笔记68:使用proguard混淆android代码
    SGU 194 Reactor Cooling
    关于流量有上下界的网络流问题的求解
    关于最小割的求解方法
    HDU 5311 Hidden String
    POJ 3548 Restoring the digits
    POJ 2062 HDU 1528 ZOJ 2223 Card Game Cheater
    ZOJ 1967 POJ 2570 Fiber Network
    HDU 1969 Pie
    HDU 1956 POJ 1637 Sightseeing tour
  • 原文地址:https://www.cnblogs.com/cdaq/p/4646858.html
Copyright © 2011-2022 走看看