zoukankan      html  css  js  c++  java
  • 寄宿于CS程序的WCF服务

    寄宿于CS程序的WCF服务

    最近项目中,需要对外部程序提供服务接口,用来进行数据交互和部分设备控制。由于都是使用的.NET平台开发的,因此想到使用WCF服务。之前也用过WCF服务,但是当初使用的时候是通过IIS寄宿的,有些地方不太让人满意,一则是同一个软件要部署两个地方,CS的桌面程序和寄宿于IIS的WCF服务部分,二则是由于系统本身问题,使用的是SQLite数据库,无法实现多线程访问,造成了数据重复,容易造成数据不一致。所以现在准备把WCF服务寄宿于CS程序中,这样就解决了以上两个问题。

    由于对WCF一知半解,只知道按部就班的使用,从明白过其中的道理,所以在网上找了些教程[1],实现了自己的想法,但其中碰到不少问题,想来还是记下,或许以后还有用处。

    本文使用一个最简单的控制台应用程序,同时通过使用WcfTestClient.exe测试,来完成这个示例。

    一、在代码中实现并配置WCF服务。

    在VS2012中创建一个控制台应用程序项目CsWcf,并添加接口ICalculator作为契约接口、类CalculatorService作为服务实现此接口中的操作方法,代码如下:

    1. ICalculator.cs--服务契约

       1: using System;
       2: using System.Collections.Generic;
       3: using System.Linq;
       4: using System.Text;
       5: using System.ServiceModel;
       6:  
       7: namespace CsWcf
       8: {
       9:     [ServiceContract]
      10:     public interface ICalculator
      11:     {
      12:         [OperationContract]
      13:         double Add(double x, double y);
      14:     }
      15: }

    2. CalculatorService.cs--服务实现

       1: using System;
       2: using System.Collections.Generic;
       3: using System.Linq;
       4: using System.Text;
       5: using System.ServiceModel;
       6:  
       7: namespace CsWcf
       8: {
       9:     public class CalculatorService:ICalculator
      10:     {
      11:         public double Add(double x, double y)
      12:         {
      13:             return x + y;
      14:         }
      15:     }
      16: }

    3. 在Program.cs中的Main函数中,添加如下代码,实现WCF服务的寄宿,并开启服务。

       1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
       2: {
       3:     host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://192.168.1.102:10002/CalculatorService");
       4:  
       5:     if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
       6:     {
       7:         ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
       8:         behavior.HttpGetEnabled = true;
       9:         behavior.HttpGetUrl = new Uri("http://192.168.1.102:10002/CalculatorService");
      10:         host.Description.Behaviors.Add(behavior);
      11:     }
      12:  
      13:     host.Opened += delegate
      14:     {
      15:         Console.WriteLine("CalculaorService已经启动,按任意键终止服务!");
      16:     };
      17:  
      18:     host.Open();
      19:     Console.Read();
      20: }

    4. F5调试执行,服务开启后,打开WcfTestClient,添加服务地址,可以正确调用Add服务函数。

    但是,以上将服务相关配置写到代码中了,这不利于后面的安装和部署。所以需要将配置信息放置在config配置文件中。

    二,使用配置文件动态配置WCF服务

    配置app.config文件,实现WCF服务的可配置性。在项目中添加应用程序配置文件,并添加以下内容:

       1: <system.serviceModel>
       2:   <behaviors>
       3:     <serviceBehaviors>
       4:       <behavior name="metadataBehavior">
       5:         <serviceMetadata httpGetEnabled="true" httpGetUrl="http://192.168.1.102:10002/CalculatorService/metadata" />
       6:       </behavior>
       7:     </serviceBehaviors>
       8:   </behaviors>
       9:   <services>
      10:     <service behaviorConfiguration="metadataBehavior" name="CsWcf.CalculatorService">
      11:       <endpoint address="http://192.168.1.102:10002/calculatorservice" binding="wsHttpBinding" 
      12:                 contract="CsWcf.ICalculator"  />
      13:       <endpoint address="http://192.168.1.102:10002/calculatorservice/MEX/" binding="mexHttpBinding" 
      14:                   contract="IMetadataExchange"  />
      15:     </service>
      16:   </services>
      17: </system.serviceModel>

    同时需要删除Program.cs中的配置代码:

       1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
       2: {
       3:     host.Opened += delegate
       4:     {
       5:         Console.WriteLine("CalculaorService已经启动,按任意键终止服务!");
       6:     };
       7:  
       8:     host.Open();
       9:     Console.Read();
      10: }

    F5调试执行,与刚刚的执行结果一样!此处要特别注意:配置节中的第二个endpoint,即MEX配置,一定要加上,否则会出现如下错误:

    错误: 无法从 http://192.168.1.102:10002/CalculatorService 获取元数据如果是您有权访问的 Windows (R) Communication Foundation 服务,请检查是否已启用在指定地址发布元数据。有关启用元数据发布的帮助,请参阅 http://go.microsoft.com/fwlink/?LinkId=65455 上的 MSDN 文档。WS-Metadata Exchange 错误 URI: http://192.168.1.102:10002/CalculatorService 元数据包含无法解析的引用:“http://192.168.1.102:10002/CalculatorService”。 Sendera:BadContextToken无法处理消息。这很可能是因为操作“http://schemas.xmlsoap.org/ws/2004/09/transfer/Get”不正确,或因为消息包含无效或过期的安全上下文令牌,或因为绑定之间出现不匹配。如果由于未处于活动状态导致服务中止了该通道,则安全上下文令牌无效。若要防止服务永久中止闲置会话,请增加服务终结点绑定上的接收超时。HTTP GET Error URI: http://192.168.1.102:10002/CalculatorService 下载“http://192.168.1.102:10002/CalculatorService”时出错。 请求因 HTTP 状态 400 失败: Bad Request。

    我在Artech的文章[1]中学习中并没有看到第二个终结点的配置,所以运行的时候一直出错,找了好久才找到这个解决办法,可以参考“WCF Part 4 : Make your service visible through metadata”这篇文章[2]

    三、其它机器访问权限限制的解决办法

    以上两步骤,我们完成了WCF服务的寄宿、发布和访问,但是如果在其它计算机上访问此WCF服务时,会发现权限提示:

    无法满足对安全令牌的请求,因为身份验证失败!

    这个时候,默认的安全是计算机名和用户名做为权限要求。如果想让其他用户也可以随时访问到些WCF服务,就需要修改配置文件中的安全级别,设置<security>的mode为None就可以了。同时更改一个endpoint的bindingConfiguration="wsHttpBindingConfiguration"。

       1: <bindings>
       2:   <wsHttpBinding>
       3:     <binding name="wsHttpBindingConfiguration" maxReceivedMessageSize="20971510">
       4:       <readerQuotas maxStringContentLength="20971520" maxArrayLength="20971520"/>
       5:       <security mode="None"/>
       6:     </binding>
       7:   </wsHttpBinding>
       8: </bindings>

    再次运行此服务,其它计算机上也可以访问此服务了。

    总结:WCF用起来简单,“制作”起来貌似也很简单,和写其它的代码基本无异,但是真正使用起来的时候,却又经常碰到这样那样的问题,个人感觉WCF是一个极其精密的仪器,操作简单,但是仪器的操作步骤和顺序却比较麻烦,而且零部件不牢固,经常脱落损坏,所以要想更好的使用它,需要对它有个很好的了解才是。由于现在网络的存在,好多东西都是用的时候搜索一下,基本没有系统、深入的学习过,这对以后的学习和工作经验的积累都用处不太大。

    [1] Artech, 我的WCF之旅(1):创建一个简单的WCF程序

    [2] Dennis van der Stelt, WCF Part 4 : Make your service visible through metadata

    ---------------------------------------------

    作者:Ritchie(乞戈
    出处:http://RitchieChen.cnblogs.com/ 
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

     
    分类: WCF学习
  • 相关阅读:
    运维面试题之系统运维
    运维面试题之linux编程
    运维面试题之linux基础
    运维面试题之网络
    python 查找日志关键字
    python 数组中数字求和是否为零
    python 时间戳和时间格式互相转换
    Appium环境搭建说明(包括报错处理)
    python操作上级子文件
    去除ufeff的解决方法,python语言
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2940930.html
Copyright © 2011-2022 走看看