从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服务 ...
随机推荐
- 使用java如何操作elasticsearch?简单示例。
在线API:https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.4/transport-client.html教程:http ...
- pwd、ln和重定向命令
pwd命令 命令功能: 使用pwd命令可以显示当前的工作目录,该命令很简单,直接输入pwd即可,后面不带参数. pwd命令以绝对路径的方式显示用户当前工作目录.命令将当前目录的全路径名称(从根 ...
- 2018-2019-2 网络对抗技术 20165301 Exp4 恶意代码分析
2018-2019-2 网络对抗技术 20165301 Exp4 恶意代码分析 实验内容 系统运行监控 使用如计划任务,每隔一分钟记录自己的电脑有哪些程序在联网,连接的外部IP是哪里.运行一段时间并分 ...
- thinkphp AOP(面向切面编程)
AOP: 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软 ...
- 000 在什么位置写js代码
一:介绍 1.DOM 2.节点分类 节点及其类型: 1). 元素节点 2). 属性节点: 元素的属性, 可以直接通过属性的方式来操作. 3). 文本节点: 是元素节点的子节点, 其内容为文本. 二:J ...
- POJ 3009 Curling 2.0(DFS + 模拟)
题目链接:http://poj.org/problem?id=3009 题意: 题目很复杂,直接抽象化解释了.给你一个w * h的矩形格子,其中有包含一个数字“2”和一个数字“3”,剩下的格子由“0” ...
- 005.基于docker部署etcd集群部署
一 环境准备 ntp配置:略 #建议配置ntp服务,保证时间一致性 etcd版本:v3.3.9 防火墙及SELinux:关闭防火墙和SELinux 名称 地址 主机名 备注 etcd1 172.24. ...
- canvas版《俄罗斯方块》
试玩(没有考虑兼容低版本浏览器): See the Pen Canvas俄罗斯方块 by 王美建 (@wangmeijian) on CodePen. ************************ ...
- 电子邮件-TCP
参考下图,由于电子邮件是最早应用于网络上的服务,而早期网络的不可靠性,才设计了TCP协议,而邮件必须要保证正确传输,而非高速,所以早期的电子邮件协议 全是基于TCP的,一直持续到现在.
- hihoCoder.1457.后缀自动机四 重复旋律7(广义后缀自动机)
题目链接 假设我们知道一个节点表示的子串的和sum,表示的串的个数cnt,那么它会给向数字x转移的节点p贡献 \(sum\times 10+c\times cnt\) 的和. 建广义SAM,按拓扑序正 ...