从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"文件:
点击"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服务的更多相关文章
- WCF分布式开发步步为赢(3)WCF服务元数据交换、配置及编程开发
今天我们继续WCF分布式开发步步为赢(3)WCF服务元数据交换.配置及编程开发的学习.经过前面两节的学习,我们了解WCF分布式开发的相关的基本的概念和自定义宿主托管服务的完整的开发和配置过程.今天我们 ...
- WCF开发实战系列三:自运行WCF服务
WCF开发实战系列三:自运行WCF服务 (原创:灰灰虫的家 http://hi.baidu.com/grayworm)上一篇文章中我们建立了一个WCF服务站点,为WCF服务库运行提供WEB支持,我们把 ...
- 网络开发之使用Web Service和使用WCF服务
判断是否有可用网络连接可以通过NetworkInterface类中的GetIsNetworkAvailable来实现: bool networkIsAvailable = networkInterfa ...
- [WCF] - 使用 bat 批处理文件将 WCF 服务部署为 Windows Service
1. 添加 Windows Service 项目 2. 添加 WCF 项目引用 3. 更新 App.config 配置文件(可以从 WCF的 Web.config 拷贝过来),设置服务地址. 4. 配 ...
- 网站/IIS/Web/WCF服务 访问共享目录 映射 的解决方案
目录 问题案例 原因分析 解决问题 总结 问题案例 环境: 电脑A:winform程序: 电脑B:部署了一个文件上传的WCF服务在IIS上.且该服务的配置文件中已经增加 <identity im ...
- 如何让WCF服务更好地支持Web Request和AJAX调用
WCF的确不错,它大大地简化和统一了服务的开发.但也有不少朋友问过我,说是在非.NET客户程序中,有何很好的方法直接调用服务吗?还有就是在AJAX的代码中(js)如何更好地调用WCF服务呢? 我首先比 ...
- WCF服务的Web HTTP方式
NET 3.5以后,WCF中提供了WebGet的方式,允许通过url的形式进行Web 服务的访问.现将WCF服务设置步骤记录如下: endpoint通讯协议设置成 webHttpBinding en ...
- GPRS GPRS(General Packet Radio Service)是通用分组无线服务技术的简称,它是GSM移动电话用户可用的一种移动数据业务,属于第二代移动通信中的数据传输技术
GPRS 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . GPRS(General Packet Radio Service)是通用分组无线服务技术的简称,它是GSM移动电话用户可 ...
- 记录:Web无引用无配置方式动态调用WCF服务
这几年一直用WebApi较多,最近项目中有个需求比较适合使用WCF,以前也用过JQuery直接调用Wcf的,但是说实话真的忘了… 所以这次解决完还是花几分钟记录一下 WCF服务端:宿主在现有Win服务 ...
随机推荐
- 高可用的MongoDB集群【转】
刚接触MongoDB,就要用到它的集群,只能硬着头皮短时间去看文档和尝试自行搭建.迁移历史数据更是让人恼火,近100G的数据文件,导入.清理垃圾数据执行的速度蜗牛一样的慢.趁着这个时间,把这几天关于M ...
- C# 压缩文件 的创建
using System;using System.IO.Compression; using System.Collections.Generic;using System.Linq;using S ...
- scrapy入门二(分页抓取文章入库)
分页抓取博客园新闻,先从列表里分析下一页按钮 相关代码: # -*- coding: utf-8 -*- import scrapy from cnblogs.items import Article ...
- Android 7.0 行为变更
Android 7.0 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更.本文重点介绍您应该了解并在开发应用时加以考虑的一些主要变更. 如果您之前发布过 Android 应用,请注意 ...
- 盒子模型与flex模型
一.盒子模型 注意:两个相邻元素的margin值是重叠在一起的,取当中最大的那个值. 水平方向auto, margin:0 auto;会居中 但是margin-left:auto;,元素会到最右 ...
- Workman启动失败的解决方法 stream_socket_server() has been disabled for security reasons
1.报如下错误,问题是php版本太低 php -ini 看下你的版本 http://doc2.workerman.net/how-distributed.html 参考: https://blog.c ...
- linux 环境变量设置方法总结(PATH / LD_LIBRARY_PATH)
PATH和LD_LIBRARY_PATH本质都是变量,所谓变量的意思就是由别人赋值产生的,直觉往往会让我们添加和减少这个变量本身的某些路径,实际上这是不正确的.正确的做法是我们要去修改赋予这个变量数值 ...
- laravel中redis队列的使用
一.配置文件 首先我们需要在配置文件中配置默认队列驱动为Redis,队列配置文件是config/queue.php: return [ 'default' => env('QUEUE_DRIVE ...
- 浅谈JavaScript DDOS 攻击原理与防御
前言 DDoS(又名"分布式拒绝服务")攻击历史由来已久,但却被黑客广泛应用.我们可以这样定义典型的DDoS攻击:攻击者指使大量主机向服务器发送数据,直到超出处理能力进而无暇处理正 ...
- .NetCore下使用Polly结合IHttpClientFactory实现聚合服务
在使用微服务的过程中经常会遇到这样的情况,就目前我遇到的问题做下分析 情况一: 这里服务对于前后端分离情况来说,多使用查询服务,前端直接获取不同服务的数据展示,如果出现其中的服务失败,对业务数据无影响 ...