zoukankan      html  css  js  c++  java
  • 从Web Service和Remoting Service引出WCF服务

    本篇先通过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"文件:

    1

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

    2

    显示如下:

    3

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

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

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

    4

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

    5


    完善"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);
    
            }

    6

    创建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"的窗体。创建如下界面:

    7

    添加对"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);
    
            }
    
        }
    
    }
    

    生成解决方案。

    运行宿主程序。

    8

    运行窗体程序。

    9


    WCF登场

     

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

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

    10

    修改"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网站。

    打开宿主应用程序。

    11

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

    12

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

    13

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

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

    14

    点击"确定"。

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

    15

    同时,自动在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="PC201312021114Administrator" />
    
            </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);
    
            }
    

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

    16

    提示需要明确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);
    
            }
    

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

    17   

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

     

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

    添加服务引用如下:

    18

    设计界面如下:

    19

    编写按钮事件如下:

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

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

    20

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


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

     

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

    就酱。

  • 相关阅读:
    有序数组中找中位数
    卡特兰数 catalan number
    海量数据等概率选取问题
    求字符串中最长无重复字符的子串
    Linux的进程通信(IPC)
    Linux多线程编程
    后缀数组处理字符串的利器
    网络编程socket基本API详解
    Windows线程的创建与终止
    《算法导论》读书笔记之第10章 基本数据结构之二叉树
  • 原文地址:https://www.cnblogs.com/darrenji/p/4630090.html
Copyright © 2011-2022 走看看