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();
    }


  • 相关阅读:
    IDEA永久激活方法
    idea在本地调试,spark创建hiveContext的时候报错
    MVC里面调用webservice
    log4net配置
    Linq 使用skip和take分页
    ASP.NET页面之间传递值的几种方式
    C#操作redis
    C#知识点:I/O
    C#知识点:ref和Out关键字浅谈
    C#知识点:反射
  • 原文地址:https://www.cnblogs.com/cdaq/p/4646858.html
Copyright © 2011-2022 走看看