本篇先通过Web Service和Remoting Service创建服务,抛砖引玉,再体验WCF服务。首先一些基本面:

什么是WCF?

Windows Communication Foundation,微软的平台,用来搭建分布式的、互操作的应用程序。

什么是分布式应用程序?

如果把计算机看成是节点,分布式应用程序跑在2个或2个以上的节点上。比如,一个应用程序运行在一台电脑上,另一个服务运行在另外一台电脑上,应用程序消费所提供的服务。

为什么需要分布式应用程序?

比如有一个应用程序的结构是数据层,业务层,表现层,而这些层可能分布在不同的电脑上。当用户请求比较少的时候,可以把这些层放在同一台服务器上,当用户请求达到一定的数量级,为了不影响性能,这时后就需要把这些层扩展到不同的服务器上。

另外,一个公司可能消费另一个公司提供的服务,这也是分布式的。

什么是互操作应用程序?

一个应用程序如果可以和任何平台上的应用程序通讯,这个应用程序就是互操纵应用程序。Web Service是互操作应用程序。.NET remoting Service不是,它只能被.NET 应用程序消费。

为什么要学WCF?

比如有2个客户端应用程序。

比如一个是Java应用程序,接收HTTP协议,需要XML格式的返回信息。为此,我们可以创建一个Web Service服务。

比如另一个是.NET应用程序,接收TCP协议,需要二进制格式的返回信息,为此,我们可以创建一个Remoting Service。

在这里,作为开发者,需要同时学会使用Web Service和Remoting Service。

而WCF统一了这些方面,只要学会WCF,就能处理上诉的应用场景。WCF提供2个end point,在end point的configuraiton中设置协议以及信息格式。

创建Web Service

大致思路是:

→ 创建Web Service
→ 客户端引用服务,并调用服务方法

创建一个空的ASP.NET Web应用程序。

添加"HelloWebService.asmx"文件。

修改如下:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
    // [System.Web.Script.Services.ScriptService]
    public class HelloWebService : System.Web.Services.WebService
    {

        [WebMethod]
        public string GetMessage(string name)
        {
            return "Hello " + name;
        }
    }

在浏览器中浏览"HelloWebService.asmx"文件:

点击"GetMessage"方法,在界面中输入实参,点击"调用"。

显示如下:

"http://localhost:3087/HelloWebService.asmx/GetMessage"这个就是获取Web Service的具体地址。

在当前的解决方案下再添加一个空的ASP.NET Web应用程序,名称为"HelloWebClient",并创建一个名称为"WebForm1.aspx"的Web窗体。

右键"HelloWebClient"下的"引用",点击"添加服务引用"。

点击"确定",在"HelloWebClient"下多了引用的Web Service。

完善"WebForm1.aspx"页面。

    <table>
         <tr>
             <td>
                 <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                 <asp:Button ID="Button1" runat="server" Text="获取信息" OnClick="Button1_Click" />
             </td>
         </tr>
         <tr>

             <td>
                 <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
             </td>
         </tr>
     </table>

当在TextBox中输入信息,点击"获取信息按钮",调用Web Service服务,就可获取到信息。

        protected void Button1_Click(object sender, EventArgs e)
        {
            HelloWebService.HelloWebServiceSoapClient client = new HelloWebService.HelloWebServiceSoapClient();
            Label1.Text = client.GetMessage(TextBox1.Text);
        }

创建Remoting Service

大致思路是:

→ 写一个接口
→ 实现接口,并派生于MarshalByRefObject
→ 宿主,注册信道,规定端口
→ 应用程序,也注册信道,调用方法

打开一个新的Visual Studio界面。

创建一个名称为"HelloRemotingService"的类库。

在该类库下创建一个"IHelloRemotingService"的接口。

namespace HelloRemotingService
{
    public interface IHelloRemotingService
    {
        string GetMessage(string name);
    }
}

在"HelloRemotingService"类库所在解决方案下创建名称为"MyRemotingService"的类库。

在"MyRemotingService"的类库中,添加对"HelloRemotingService"类库的引用。

在"MyRemotingService"中添加名称为"Hello"的类文件。

using HelloRemotingService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyRemotingService
{
    public class Hello : MarshalByRefObject, IHelloRemotingService
    {
        public string GetMessage(string name)
        {
            return "Hello" + name;
        }
    }
}


现在需要宿主。在当前解决方案下添加一个名称为"RemotingServiceHost"的控制台应用程序。并添加对"HelloRemotingService"类库和MyRemotingService"类库的引用,再添加"System.Runtime.Remoting"组件。

......
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using MyRemotingService;

namespace RemotingServiceHost
{
    class Program
    {
        static void Main(string[] args)
        {
            Hello h = new Hello();

            //信道
            TcpChannel channel = new TcpChannel(9090);

            //向信道服务注册信道
            ChannelServices.RegisterChannel(channel,true);

            //注册服务端对象
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(Hello), "GetMessage", WellKnownObjectMode.Singleton);

            Console.WriteLine("Remoting service启动了 @" + DateTime.Now);
            Console.ReadKey();

        }
    }
}

在解决方案下创建一个名称为"HelloRemotingServiceClient"的窗体。创建如下界面:

添加对"HelloRemotingService"类库和MyRemotingService"类库的引用,再添加"System.Runtime.Remoting"组件。

......
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using MyRemotingService;


namespace HelloRemotingServiceClient
{
    public partial class Form1 : Form
    {

        IHelloRemotingService client;
        public Form1()
        {
            InitializeComponent();
            TcpChannel channel = new TcpChannel();
            ChannelServices.RegisterChannel(channel, true);
            client = (IHelloRemotingService)Activator.GetObject(typeof(IHelloRemotingService), "tcp://localhost:9090/GetMessage");
        }



        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = client.GetMessage(textBox1.Text);
        }
    }
}


生成解决方案。

运行宿主程序。

运行窗体程序。

WCF登场

在Visual Studio中创建一个名称为"HelloWcf"的类库。

在"HelloWcf"的类库添加一个名称为"FirstWcf"的"WCF 服务",项目自动为我们创建了"IFristWcf"和"FirstWcf"两个类文件,并自动添加了对"System.ServiceModel"的引用。

修改"IFirstWcf"接口:

namespace HelloWcf
{
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IFirstWcf”。
    [ServiceContract]
    public interface IFirstWcf
    {
        [OperationContract]
        string GetMessage(string name);
    }
}

修改"FirstWcf"类:

namespace HelloWcf
{
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“FirstWcf”。
    public class FirstWcf : IFirstWcf
    {
        public string GetMessage(string name)
        {
            return "Hello " + name;
        }
    }
}

现在需要宿主。在当前解决方案下添加一个"WcfHost"的控制台应用程序。

为"WcfHost"添加对"System.ServiceModel"的引用。

为"WcfHost"添加对"HelloWcf"类库的引用。

再为"WcfHost"配置end point, 需要添加2个end point,一个用来接收HTTP协议,一个用来接收TCP协议。

在App.config中配置如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
      <services>
        <service name="HelloWcf.FirstWcf" behaviorConfiguration="mexBehaviour">
          <endpoint address="HelloWcf" binding="basicHttpBinding" contract="HelloWcf.IFirstWcf"></endpoint>
          <endpoint address="HelloWcf" binding="netTcpBinding" contract="HelloWcf.IFirstWcf"></endpoint>
          <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
          <host>
            <baseAddresses>
              <add baseAddress="http://localhost:9090"/>
              <add baseAddress="net.tcp://localhost:6060"/>
            </baseAddresses>
          </host>
        </service>
      </services>

      <behaviors>
          <serviceBehaviors>
            <behavior name="mexBehaviour">
              <serviceMetadata httpGetEnabled="true"/>
            </behavior>
          </serviceBehaviors>
      </behaviors>

    </system.serviceModel>
</configuration>

把"WcfHost"设置为启动程序。

再启动一个新的Visual Studio。

■ Web客户端消费WCF服务

创建一个名称为"WcfClient"的空的ASP.NET网站。

打开宿主应用程序。

在浏览器中输入:http://localhost:9090

点击"http://localhost:9090/?wsdl"链接。

以上的的xml格式和Web Service是很像的。

回到名称为"WcfClient"的空的ASP.NET网站,右键"引用",点击"添加服务引用",填写如下:

点击"确定"。

这时,自动添加了对"System.ServiceModel"的引用,自动添加了"Service References"文件。

同时,自动在Web.config中增加了<system.serviceModel>节点。

<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IFirstWcf" />
      </basicHttpBinding>
      <netTcpBinding>
        <binding name="NetTcpBinding_IFirstWcf" />
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:9090/HelloWcf" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IFirstWcf" contract="HelloService.IFirstWcf"
        name="BasicHttpBinding_IFirstWcf" />
      <endpoint address="net.tcp://localhost:6060/HelloWcf" binding="netTcpBinding"
        bindingConfiguration="NetTcpBinding_IFirstWcf" contract="HelloService.IFirstWcf"
        name="NetTcpBinding_IFirstWcf">
        <identity>
          <userPrincipalName value="PC201312021114\Administrator" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

添加一个aspx文件,编写如下:

    <div>
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="获取信息" OnClick="Button1_Click" />
        <br />
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </div>

编写按钮事件如下:

        protected void Button1_Click(object sender, EventArgs e)
        {
            HelloService.FirstWcfClient client = new HelloService.FirstWcfClient();
            Label1.Text = client.GetMessage(TextBox1.Text);

        }

浏览该页面,点击按钮,发生如下报错:

提示需要明确end point。

我们需要用到Web.config中的如下节点:

<endpoint address="http://localhost:9090/HelloWcf" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IFirstWcf" contract="HelloService.IFirstWcf"
        name="BasicHttpBinding_IFirstWcf" />         

修改按钮事件如下:

        protected void Button1_Click(object sender, EventArgs e)
        {
            HelloService.FirstWcfClient client = new HelloService.FirstWcfClient("BasicHttpBinding_IFirstWcf");
            Label1.Text = client.GetMessage(TextBox1.Text);

        }

再次浏览页面,输入内容,点击按钮,一切正常。

■ 窗体应用程序消费WCF服务

重新打开一个Visual Studio, 创建一个名称为"WcfFormClient"的窗体应用程序。

添加服务引用如下:

设计界面如下:

编写按钮事件如下:

        private void button1_Click(object sender, EventArgs e)
        {
            HelloServiceTwo.FirstWcfClient client = new HelloServiceTwo.FirstWcfClient("NetTcpBinding_IFirstWcf");
            label1.Text = client.GetMessage(textBox1.Text);
        }

运行窗体应用程序,输入内容,点击按钮,一切正常。

至此,通过WCF的2个end point,客户端既可以使用HTTP协议通讯,也可以使用TCP协议通讯。

总结一下WCF服务的调用过程:

→ 创建WCF服务,自动生成一个接口和实现类
→ 宿主需要添加对"System.ServiceModel"的引用以及WCF服务所在类库的引用
→ 在宿主的配置文件中配置<system.serviceModel>节点,以及end point等信息
→ 客户端程序添加对WCF服务的引用
→ 客户端在声明WCF服务代理类实例的时候,需要明确指出使用哪一个end point

就酱。

从Web Service和Remoting Service引出WCF服务的更多相关文章

  1. WCF分布式开发步步为赢(3)WCF服务元数据交换、配置及编程开发

    今天我们继续WCF分布式开发步步为赢(3)WCF服务元数据交换.配置及编程开发的学习.经过前面两节的学习,我们了解WCF分布式开发的相关的基本的概念和自定义宿主托管服务的完整的开发和配置过程.今天我们 ...

  2. WCF开发实战系列三:自运行WCF服务

    WCF开发实战系列三:自运行WCF服务 (原创:灰灰虫的家 http://hi.baidu.com/grayworm)上一篇文章中我们建立了一个WCF服务站点,为WCF服务库运行提供WEB支持,我们把 ...

  3. 网络开发之使用Web Service和使用WCF服务

    判断是否有可用网络连接可以通过NetworkInterface类中的GetIsNetworkAvailable来实现: bool networkIsAvailable = networkInterfa ...

  4. [WCF] - 使用 bat 批处理文件将 WCF 服务部署为 Windows Service

    1. 添加 Windows Service 项目 2. 添加 WCF 项目引用 3. 更新 App.config 配置文件(可以从 WCF的 Web.config 拷贝过来),设置服务地址. 4. 配 ...

  5. 网站/IIS/Web/WCF服务 访问共享目录 映射 的解决方案

    目录 问题案例 原因分析 解决问题 总结 问题案例 环境: 电脑A:winform程序: 电脑B:部署了一个文件上传的WCF服务在IIS上.且该服务的配置文件中已经增加 <identity im ...

  6. 如何让WCF服务更好地支持Web Request和AJAX调用

    WCF的确不错,它大大地简化和统一了服务的开发.但也有不少朋友问过我,说是在非.NET客户程序中,有何很好的方法直接调用服务吗?还有就是在AJAX的代码中(js)如何更好地调用WCF服务呢? 我首先比 ...

  7. WCF服务的Web HTTP方式

    NET 3.5以后,WCF中提供了WebGet的方式,允许通过url的形式进行Web 服务的访问.现将WCF服务设置步骤记录如下: endpoint通讯协议设置成  webHttpBinding en ...

  8. GPRS GPRS(General Packet Radio Service)是通用分组无线服务技术的简称,它是GSM移动电话用户可用的一种移动数据业务,属于第二代移动通信中的数据传输技术

    GPRS 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . GPRS(General Packet Radio Service)是通用分组无线服务技术的简称,它是GSM移动电话用户可 ...

  9. 记录:Web无引用无配置方式动态调用WCF服务

    这几年一直用WebApi较多,最近项目中有个需求比较适合使用WCF,以前也用过JQuery直接调用Wcf的,但是说实话真的忘了… 所以这次解决完还是花几分钟记录一下 WCF服务端:宿主在现有Win服务 ...

随机推荐

  1. Longest Words

    Given a dictionary, find all of the longest words in the dictionary. Example Given { "dog" ...

  2. 管中窥豹:从Page Performance看Nand Flash可靠性【转】

    转自:https://blog.csdn.net/renice_ssd/article/details/53332746 如果所有的page performace在每次program时都是基本相同的, ...

  3. expect学习笔记及实例详解【转】

    1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1 首行加上/usr/bin/expect1.2 spawn: 后面加上需要执行的shell命令,比如说sp ...

  4. Python发送邮件:smtplib、sendmail

    本地Ubuntu 18.04,本地Python 3.6.5, 阿里云Ubuntu 16.04,阿里云Python 3.5.2, smtplib,sendmail 8.15.2, 今天,打算实现通过电子 ...

  5. 【论文阅读】Learning Spatial Regularization with Image-level Supervisions for Multi-label Image Classification

    转载请注明出处:https://www.cnblogs.com/White-xzx/ 原文地址:https://arxiv.org/abs/1702.05891 Caffe-code:https:// ...

  6. 【推荐】关于JS中的constructor与prototype【转】

    最初对js中 object.constructor 的认识: 在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下 ...

  7. 【LOJ】#2527. 「HAOI2018」染色

    题解 简单容斥题 至少选了\(k\)个颜色恰好出现\(S\)次方案数是 \(F[k] = \binom{M}{k} \frac{N!}{(S!)^{k}(N - i * S)!}(M - k)^{N ...

  8. Codeforces 280C Game on Tree 期望

    Game on Tree 这种题好像在wannfly训练营讲过, 我怎么又不会写啦, 我好菜啊啊啊. 我们按每个点算贡献, 一个点有贡献就说明它是被选中的点, 那么它被选中的概率就为1 / depth ...

  9. 桌面图形化安装的CentOS6.7中默认安装的yum不能正常使用

    使用rpm -qa|grep yum,可以发现有好多关于yum的安装插件等东西... 从里面将的一些东西删除掉,只留下下面三个即可,其余的全部删除掉rpm -e yum-plugin-security ...

  10. mysql排序数据

    一:order by的普通使用 1.介绍 当使用SELECT语句查询表中的数据时,结果集不按任何顺序进行排序.要对结果集进行排序,请使用ORDER BY子句. ORDER BY子句允许: 对单个列或多 ...