“轻松掌握WCF 帮你找到入门砖”访谈实录

3月24日下午2:00到3:00,51CTO邀请张逸和赵劼两位老师,就“轻松掌握WCF 帮你找到入门砖”这一主题进行现场讨论,并回答网友在工作和学习中的难题。下面是本次嘉宾访谈的对话实录:

开场白

主持人:现在两位老师已经来到了我们的聊天室,先给大家打个招呼!同时,也给大家先简单做下自我介绍吧!
张逸:大家好!
张逸:我是《WCF服务编程》的译者,对WCF有一定的经验,也曾利用WCF开发过一些项目,希望这次交流能够对大家学习WCF有一定的帮助。
赵劼:大家好!我是个开发人员。平时对于.NET开发相关方面有比较大的兴趣,也投入了不少。主要“功绩”就在于写了一些技术文章。WCF目前已经是微软分布式通信的“事实标准”(已经有这个倾向了),对于这方面有需求的朋友了解一下WCF还是很重要的。

WCF简介

张逸:我先解释一下WCF是什么?
张逸:严格的说,WCF就是专门 用于服务定制、发布与运行以及消息传递和处理的一组专门类的集合,也就是所谓的“类库”。这些类通过一定方式被组织起来,共同协作,并为开发者提供了一个 统一的编程模式。WCF之所以特殊,是在于它所应对的场景与普通的.NET类库不同,它主要用于处理进程间乃至于机器之间消息的传递与处理,同时它引入了 SOA的设计思想,以服务的方式公布并运行,以方便客户端跨进程和机器对服务进行调用。实际上,WCF就是微软对于分布式处理的编程技术的集大成者,它将 DCOM、Remoting、Web Service、WSE、MSMQ集成在一起,从而降低了分布式系统开发者的学习曲线,并统一了开发标准。

主持人:您接触WCF有多长时间了呢?

张逸:应该说,我从WCF的前身indigo开始,就对其产生了极大的兴趣,毕竟我最初使用.NET Remotin开发了一些项目,对分布式开发比较热衷于了解。
张逸:从WCF 所处的位置来看,它是包含在.NET 3.0(也包括.NET 3.5)之中的。我们注意比较.NET 3.0与.NET 2.0,其实唯一的区别就是.NET 3.0包含了WCF、WPF、WF(或者还有CardSpace)而已。因此,我们认为WCF是.NET框架的一部分,似乎并不为过。尤为关键的是, WCF并不能脱离.NET框架而单独存在(但非WCF客户端可以调用WCF服务),因此,虽然WCF是微软用以应对SOA解决方案的开发需求而专门推出 的,但它并不是例如Spring、Struts那样的框架,也不是像EJB那样的容器或者服务器。微软真正符合SOA企业应用服务器角色的,我想应该是 Biztalk Server。

现场问题解答

1、网友提问:学习WCF需要什么知识背景吗?
张逸:
学习WCF并不难,其实掌握.NET的基本知识就可以入手WCF了。当然,如果多了解有关分布式开发和SOA的相关知识,会比较容易理解其中的一些概念。

2、网友提问:我在xbap里想调用WCF,用的是TCP/IP协议,但是权限被沙箱锁了,有什么办法可以实现调用WCF服务!? xbap的部署是部署到IIS里的!!我在xbap里想调用WCF,用的是TCP/IP协议,但是权限被沙箱锁了,有什么办法可以实现调用WCF服务!? xbap的部署是部署到IIS里的!!

赵劼:关于XBAP的权限问题,这个和AJAX一样,因为要保证性能问题,因此运行在一个Security Sandbox。解决方法也和AJAX一样,用服务器端作代理即可。
赵劼:解决XBAP的砂箱限制的方法,就是使用服务器端作为代理来访问WCF服务。
张逸:同意老赵的观点。微软的技术都是如此,应用简单,深入则困难。因为微软的设计师们有一套化繁为简的本事。但若要理解如何化繁为简的,就需要你深入研究了。
赵劼:简单的说,就是让您的XBAP程序请求您自己的某个资源(比如某个HttpHandler或WCF service),然后您的后台程序接收到请求后,再去请求您的目标服务,然后您的后台程序把结果返回给XBAP。

3、网友提问:为什么要用WCF,我初学,WCF有什么好处?

赵劼:WCF目前已经是微软分布式通信的“事实标准”(已经有这个倾向了),对于这方面有需求的朋友了解一下WCF还是很重要的。
张逸:简单说,WCF就是将你提到的所有这些与服务相关、与分布式开发相关的微软技术集成在一起了。你用WCF可以解决以前需要多种技术才能实现的问题。
赵劼:如果您的工作需要(也就是需要在.NET平台下使用分布式通信),自然学习WCF是不二的选择。
张逸:如果你不打算开发企业应用程序,并且不会碰到互操作性的问题,同时不考虑可扩展性的要求,以及解决企业系统之间信息孤岛的问题,我觉得自然不必学习WCF。反过来说,上述的这些场景正是WCF的用武之地。

4、网友提问:弱弱地问:WCF程序编写起来容易吗?需要掌握什么样的基础?

张逸:编写WCF程序非常容易,如果你只是WCF的应用者,只需要掌握一些WCF特有的attribute就可以了。

主持人:可以举例说明吗?

张逸:例如[ServiceContract]、[DataContract]等。因为WCF的编程模式与传统的编程模式区别不大。这也是微软的一个良苦用心(也可以说是险恶用心:-)),这样就降低了学习者的技术门槛。
张逸:WCF的服务编程自然还是基于Windows平台的。
赵劼:当然,这是微软技术的一贯特点,使用简单。但是如果要深入的话,还是要投入不少精力的。.NET 3.0中的部件是用于处理企业级需求的,由于业务各不相同,灵活多变,因此WCF的高级部分必然也会引入相当的复杂度和灵活度。

5、网友提问:WCF里的remoting的性能比.net 2.0的remoting的性能好要很多吗?

张逸:不知老赵有没有对性能进行过测试,坦白说,我没有对.NET Remoting和WCF进行性能的比对,这个问题不能贸然回答,呵呵!
赵劼:我没有做过系统的性能测试,但是微软官方曾经发布过一篇白皮书,表示在同样(或类似)的协议下,WCF的性能普遍优于.NET之前的分布式通信解决方案。我相信NetTcpBinding性能优于.net Remoting。

6、网友提问:可否举一个现实中的例子来说明什么样的需求,使用WCF解决更好?

赵劼:关于“什么样的需求,使用WCF解决更好”,感觉不是很好回答。
其实WCF其实也已经逐渐成为.NET下分布式通信的标准技术了。如果您有这方面需求自然需要学习。例如:对外释放Web Service。系统应用服务器对外交互,系统中基于MSMQ的异步操作,等等。

7、网友提问:可否给出编程中通用的事例Hello来进行讲解?

张逸:其实,cool所说的例子,网上有很多。用WCF编写hello,很简单:

using System.ServiceModel;
[ServiceContract]
public interface IHello
{
[OperationContract]
void SayHello(string msg);
}
public class Hello:IHello
{
public void SayHello(string msg)
{
Console.WriteLine(msg);
}
}

张逸:呵呵!上述例子中除了几个Attribute之外,和普通编程没有太大区别。唯一不同的是,当我们开发了这个服务之后,还需要Host。

8、网友提问:请两位老师简单地说一下,您们认为WCF最大的优势在哪?

赵劼:个人认为WCF的最大优势在于统一和简化了分布式技术的运用。以前使用不同的分布式技术,写法大相径庭。 而现在,往往只需要进行Attribute标记,再加上配置就可以实现不同技术下的分布式通信了。这样让程序员把更多精力可以放在业务相关的逻辑上,而不 会拘泥于技术实现本身。

9、网友提问:WCF最大的优点是不是就是在接口不变的情况下,可以修改通信方式?如果我暂时没有这样的需求是不是可以先不考虑使用WCF?换句话说,从remoting到WCF切换有什么风险?

赵劼:从Remoting到WCF切换的风险主要还是在于工程上,而不是技术上。一般说来,Remoting能够实现的功能WCF都能够胜任,但是此类“移植”的工作也有很多与技术无关的问题,比如耗费的成本,移植后所带来的风险等等。
张逸:如果仅局限于在局域网中的话,如果已经用Remoting开发了一个很稳定的系统,我并不建议草率地将其升级为WCF。

10、主持人:利用WCF,不同系统之间可以进行通信,同时,层与层之间也可以基于WCF来进行通信。对于UI层与BLL层之间的 通信,如果是基于WPF或WinForm的C/S架构,那么基于WCF是非常方便的,但是如果是B/S的架构,ASP.NET页面与业务逻辑层可能部署在 同一个IIS中,以前可以直接基于API来调用业务逻辑层,现在有无必要也基于WCF来实现?

赵劼:“分布式应用的第一条准则就是不分布式”,分布式通信相对于进程间通信的确会带来较为明显的性能降低,像 您说的情况,比如ASP.NET的Web层和业务逻辑,很可能就不应该使用WCF来通信。事实上,如果用Java一脉的技术来说,以前EJB远程访问横 行,但是现在的互联网应用几乎都不太适用EJB了,而是使用Struct、Spring等轻量级框架,因为远程通信代价很高。
张逸:选 择某种技术,首先要看其具体应用的场景和需求,而不是觉得这门技术好或者新就选用。对于B/S系统而言,如果需求没有要求其他系统采用服务的方式调用该 B/S系统,那就没有必要采用WCF技术。最合理的方式是,在B/S系统中,专门设计一个服务层,体现所谓面向服务的特点,这个服务层中的服务相对粒度较 粗一点,而且应该是其他系统可能会调用的。我们可以事先考虑到这一层的设计。它并不一定是B/S系统内部调用,而是考虑未来的扩展。

11、网友提问:我还有一个问题,我觉得WCF还是没有一个明显的应用服务器。如果部署在iis的,那其实就是web service了吧!不知道WCF是否会有一个真正的应用服务器,就好像com+和ejb的应用服务器那样,提供完整的组件管理,调度,负载均衡等功能。

张逸:其实BizTalk就是很好的一个应用服务器。当然,我们也可以利用WCF开发一个轻量级的应用服务器。 网上有这方面的文章。 赵劼:当然,万事不能一概而论,对于一些企业应用,或者大规模的系统集成,很可能也是需要使用WCF将业务逻辑进行释放。这也就是为什么互联网应用大都不 需要单独的应用服务器,而企业应用很多都会有独立的应用层。

12、网友提问:WCF程序现在的稳定程度如何?可以大规模在企业开发中应用吗?

张逸:目前WCF已经得到足够的发展,稳定性方面完全能够适用于企业开发。唯一美中不足的是,对于Internet场景,利用HttpBinding传输的方式,在性能上还存在一定的局限性。

13、网友提问:WCF有哪些扩展点?比如我自定义transfer sink,自己在传输链路中加入安全机制等?

赵劼:WCF提供了很灵活也很复杂的扩展。我没有理解您的意思,如果您只是说实现自己的安全机制,这个自然可以。但是如果您是指在TCP/IP协议级别(或类似的通信级别)的扩展,那么很明显WCF就无能为力了。

4、网友提问:WCF支持一个接口暴露成RSET服务吗?

赵劼:在.NET 3.5中提供了WCF HTTP Service,专为释放RESTful接口而设计。
张逸:目前WCF支持对绑定和行为的扩展。建议你阅读一下MSDN中Aaron Skonnard的文章,他对于这些内容已经做了很好的介绍。您可以看看这篇文章:http://msdn.microsoft.com/msdnmag/issues/07/12/ServiceStation/Default.aspx?loc=zh。另外,WCF 3.5支持REST服务。

15、网友提问:有人说WCF是Vista的组成部分,确实是这样吗?它们之间有什么关系?

赵劼:Vista包含了WCF,但是WCF是个可以独立于Vista的组件,例如您也可以在Server 2003中安装使用。

16、网友提问:Ajax调用WCF,会不会加重服务器的承受能力?

赵劼:WCF本身不会对服务器增大压力,带来压力的一般都是业务本身。也就是说,WCF很难成为性能瓶颈。不会因为AJAX调用WCF而造成性能问题。

17、网友提问:Remoting有一种工厂方式的创建边界对象的方法使用还很广泛,WCF中好像没找到对应的方式。WCF里有Duplex消息交换模式,但还是不能解决remoting客户端从一个简单接口批量获取一群边界对象的问题,至少不能完全代替。
张逸:不明白您所指,是否是说Remoting中采用Marshal方式创建对象呢?
张逸:边界对象是说BoundObject?
网友提问:就是说能调用远程方法的对象。就是说在服务端声明一个Marshalbyref的对象,然后用一个工厂方法去获取这个对象。当然这个工厂方法也要暴露为remoting接口,这样客户端就可以是用这个工厂方法一下获取好多远程对象来使用。
张逸:我认为WCF包含的三种实例模式,完全涵盖了过去Remoting的三种激活模式。
张逸:现在WCF对于客户端的增强,不仅仅体现在Deplex上,而且WCF对回调方法的强有力支持,已经加强了服务端与客户端的交互能力。
张逸:我明白了您的问题了,这个问题我以前在学习Remoting的时候,提出过。实际上,现在利用WCF的ChannelFactory就能够实现这一目标。在《WCF服务编程》中也将其分为管理方式与编程方式两种。

18、网友提问:WCF如何使用linq to sql实现企业级应用!?

赵劼:LINQ to SQL和WCF其实没有必然联系,一个是数据访问技术,一个是分布式通信技术,可以随意搭配使用。当然,可能也有一点需要注意的地方,那就是LINQ to SQL的一些类型比如EntitySet,是不能被WCF序列化的,传输的时候转换成其他数据类型。
赵劼:AJAX调用WCF本身不会造成性能问题,性能问题往往是由程序开发引起的。WCF和AJAX本身都是很纯粹的技术,合理运用不会有任何问题。
张逸:其实老赵说的对象序列化的问题,也是目前我对WCF不满意的地方。这增加了使用WCF的难度。

19、网友提问:WCF在问题排查方面容易吗?比如抓dump和抓网络包等,有很容易的调试及排查问题的方案吗?

赵劼:WCF其实其本质就是普通的分布式通信技术,以往用于排查问题的手段和工具都可以使用。当然,一些WCF框架特有的方式有时候也会出现奇效,例如自己编写一个用于Debug的扩展“插入”WCF的执行过程中。
张 逸:对您提出的问题排查问题,其实与WCF本身技术无关。不过有一点,分布式程序的测试本身比较困难一点,visual studio 2008针对WCF推出了一些小工具,可以在设计服务的时候,就能够模拟客户端对服务进行测试,但没有类似于Linux下dump之类对于网络传输和数据 包之类的工具。

20、网友提问:我用x509验证,但比不用要慢好几秒,请问如何可以提高验证的较率!?

赵劼:是每次调用都会慢几秒吗?个人觉得不应该这样,您遇到的是不是只是初始化时比较耗时的问题呢?
张逸:您提出的问题比较深入,关于安全的问题,恐怕存在性能和安全的权衡。如需要加强安全,对性能就不可避免会有影响。所以,《WCF服务编程》的作者建议,先恶意地揣测最危险的,然后根据具体场景逐步降低对安全的要求。

21、网友提问:作为Java用户,WCF的出现让我应该注意些什么吗?

张逸:如果你是Java的开发者,如果需要开发与.NET程序交互的系统时,恐怕就要学习WCF了。至于如何学习,最好能够理解.NET的一些专用的与Java不同的地方。其实内部的运行机制还是很相似的,包括托管、应用程序域等等。最主要的是要理解SOA的特质。
赵劼:作 为Java用户,可能最关心的就是和WCF的Inteop的问题了。其实WCF实现了很多基于标准的通信协议。一般来说不会出现问题。此外,WCF也已经 能够很好的支持RESTful API了,因此和各种技术之间互操作性上大都也就没有问题了。因为RESTful使用了HTTP协议,这个协议早就被广泛采纳了。

22、网友提问:WS-寻址,WS-可靠性和WS-安全性。这三点不知道将来会不会全面支持WS-I规范?

张逸:您的问题不好回答,不过WCF对WS-*的支持绝对是完全的,但有个问题是这涉及到许多利益相关者之间的博弈。
张逸:p2p在xp下是能够支持的,但要指定好对等网名、唯一的路径和端口。
赵劼:P2P如果要在WCF中使用的话,还需要在Windows XP 上安装PNRP,您可以在互连网上搜索一下相关内容。
张逸:xp应该是在sp1之上才可以的。
赵劼:而如果您用XP SP2的话应该是可以的。

posted on 2008-03-25 15:40 张逸 阅读(2890) 评论(31)  编辑 收藏 所属分类: WCF Tips

评论

#1楼  2008-03-25 15:57 jillzhang      

wcf和ws的抓包要比传统程序更为简单,可以用tcpTrace或者trace ulitiy来抓取soap报文   回复  引用  查看    

#2楼  2008-03-25 16:04 留恋星空      

学习了   回复  引用  查看    

#3楼  2008-03-25 16:13 长空新雁      

好资料,学习中   回复  引用  查看    

#4楼  2008-03-25 16:37 TerryLee      

WCF并不能脱离.NET框架而单独存在(但非WCF客户端可以调用WCF服务)
---------------------------------------------------------
应该是笔误吧,“但非.NET客户端可以调用WCF服务”?   回复  引用  查看    

#5楼  2008-03-25 16:49 dudu      

对于第10个问题:
“分布式通信相对于进程间通信的确会带来较为明显的性能降低,像您说的情况,比如ASP.NET的Web层和业务逻辑,很可能就不应该使用WCF来通信。”

我们可以通过直接引用把WCF当作普通接口在进程内调用,WCF服务不仅可以作为对外服务接口,而且可以作为表现层的服务接口,这正是WCF的优势所在,博客园在博客程序的重构中正考虑在服务层使用WCF。
请看一下这篇博客:http://weblogs.asp.net/pglavich/archive/2007/08/10/architecture-wcf-services-and-caching.aspx
  回复  引用  查看    

#6楼  2008-03-25 16:54 jillzhang      

@dudu
如果进程内使用的话,那么service和client应该处于不同的AppDomain,在性能上应该也有一定的损失吧,这种损失可能比进程间通讯要小一些.   回复  引用  查看    

#7楼  2008-03-25 16:59 dudu      

@jillzhang
就是普通接口调用,怎么会在不同的AppDomain。
直接引用WCF服务所在的dll,然后:
WCFService.Contract.ICommentService commentService = new WCFService.Service.CommentService();   回复  引用  查看    

#8楼  2008-03-25 17:34 Tristan(Guozhijian)      

--引用--------------------------------------------------
dudu: @jillzhang
就是普通接口调用,怎么会在不同的AppDomain。
直接引用WCF服务所在的dll,然后:
WCFService.Contract.ICommentService commentService = new WCFService.Service.CommentService();
--------------------------------------------------------

因为WCF是基于接口编程的,所以可以当作普通的接口抽象来使用。
这样它就不是WCF了,只是普通的接口抽象
而不能说,我用WCF作为业务层的服务接口。   回复  引用  查看    

#9楼  2008-03-25 18:01 Jeffrey Zhao      

--引用--------------------------------------------------
dudu: 我们可以通过直接引用把WCF当作普通接口在进程内调用
--------------------------------------------------------
那怎么还能称为WCF通信,赫赫……只是WCF的写法方便直接普通地使用而已。
如果真用WCF做分布式通信的话,真不适合博客园,通信成本提高太多,几乎没有带来任何优势,Web服务器+数据库服务器就够了。
  回复  引用  查看    

#10楼  2008-03-25 18:02 dudu      

@Tristan(Guozhijian)
我觉得应该这样理解:WCF支持直接的接口调用。
用WCF作为业务层的服务接口,既可以通过直接的接口调用,也可以通过其他方式来调用(不要改任何WCF服务的任何代码),这就是用WCF作为业务层服务接口的好处。   回复  引用  查看    

#11楼  2008-03-25 18:27 jillzhang      

@Jeffrey Zhao
我赞同老赵
  回复  引用  查看    

#12楼 [楼主] 2008-03-25 19:42 张逸      

@TerryLee
呵呵,是笔误,我主要去强调不使用WCF的客户端了。   回复  引用  查看    

#13楼  2008-03-25 22:31 crabo [未注册用户]

--引用--------------------------------------------------
@dudu
用WCF作为业务层的服务接口,既可以通过直接的接口调用,也可以通过其他方式来调用(不要改任何WCF服务的任何代码),
-----------------------------------------------------

能否举个实例,展现进程内接口调用,和进程间Binding呼叫, 而仅仅通过配置就能达到?

迫切等待, 谢谢!   回复  引用    

#14楼  2008-03-25 22:58 IamV      

两位的文章看了很多 学习了不少知识!
谢谢!努力+ing!!   回复  引用  查看    

#15楼  2008-03-26 09:19 蛙蛙池塘      

俺去参加活动了,不知道幸运用户,寄俺一本WCF书。   回复  引用  查看    

#16楼  2008-03-26 09:54 dudu      

@crabo
“仅仅通过配置就能达到”,不太明白你的意思。   回复  引用  查看    

#17楼  2008-03-26 09:55 overred      

@蛙蛙池塘
如果送你书。。借我看看   回复  引用  查看    

#18楼  2008-03-26 10:49 苹果非 [未注册用户]

LZ,

昨天下午我也准备去聊天室的,后来因为有事没有去成,真是遗憾啊,
问题我就方在这里问拉,

WCF中.NET对象 最终转为化字节流是不是要经过2次序列化和一次编码呢
第一次序列化是.NET 对象到 MESSAGE对象
第二次序列化是.MESSAGE 对象到 XML Infoset(而这个XML Infoset包含3中形式(Binary;Text和MTOM)
最后 ,编码就是 XML Infoset到字节流(Byte Stream)过程,
不知道我说的对吗?
  回复  引用    

#19楼  2008-03-26 14:36 deserteagle [未注册用户]

对啊,配置文件搞定!   回复  引用    

#20楼  2008-03-26 15:43 蛙蛙池塘      

@overred
关键是没送,也不知道送不送,呵呵,那聊天室是匿名的,我感觉根本没打算送好像,要不他怎么知道我是我呢。   回复  引用  查看    

#21楼  2008-03-26 16:38 苹果非 [未注册用户]

我发个WCF群:13960774
欢迎大家加入哦   回复  引用    

#22楼  2008-03-26 17:39 孙淑娟 [未注册用户]

蛙蛙同学,看到你的留言了,你确实是获奖网友(http://bbs.51cto.com/viewthread.php?tid=461402&page=2&extra=page%3D1#pid1623797)。请联系我(sunsj@51cto.com)!谢谢!   回复  引用    

#23楼  2008-03-26 18:45 Betree Xing      

WCF性能低于Remoting???

早些时候, 我打算把项目的通信方式从.net remoting 升级到wcf , 升级之前, 做了一个简单的测试, 结果得出了让我十分失望的结论: 在本机, 局域网, Internet三种环境下, WCF中NetTcpChannel 较 .Net Remoting 中的TcpChannel效率都要差一些, 我希望楼主老大能找到我代码中的问题推翻这个结论, 因为我也十分希望我的结论是错误的, 希望楼主老大这样权威的.net分布式编程专家能抽空做一下性能测试, 谢谢.

测试代码实现一个客户端向服务器传送人员资料(Person)类. 服务器和客户端均用WCF和.net remoting两种方式实现这一功能.


PersonService类库(包括Person类和IPersonService服务契约, 由服务端和客户端共同引用):
==================================================
//WCF服务契约:
namespace PersonService
{
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IPersonService
{
[OperationContract(IsInitiating = true, IsTerminating = false)]
void Enter();

[OperationContract(IsInitiating = false, IsTerminating = false)]
void ReceivePersonList(IList<Person> personList);

[OperationContract(IsInitiating = false, IsTerminating = true)]
void Leave();
}
}
//person 类
namespace PersonService
{
[Serializable]
public class Person
{
//properties
public int Age;

private double weight;
public double Weight
{
get { return this.weight; }
set { this.weight = value; }
}

private double height;
public double Height
{
get { return this.height; }
set { this.height = value; }
}

private string name;
public string Name
{ get { return this.name; } }

//constructors
public Person(string name)
{
this.name = name;
}

public Person(string name, double weight, double height)
: this(name)
{
this.weight = weight;
this.height = height;
}

//methods
public static bool operator ==(Person a, Person b)
{
if (a.weight == b.weight && a.height == b.height)
return true;
else
return false;
}

public static bool operator !=(Person a, Person b)
{
return !(a == b);
}

public override bool Equals(object obj)
{
return base.Equals(obj);
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public void Die()
{ }
}
}


==================================================Server端主要代码:
==================================================
namespace PersonServer
{
class Program
{
static void Main(string[] args)
{
PersonServer personServiceSingletonOjbect = new PersonServer(); //person server singleton object

//wcf service
ServiceHost host = new ServiceHost(personServiceSingletonOjbect, new Uri("net.tcp://localhost:11111/"));
host.AddServiceEndpoint(typeof(PersonService.IPersonService), new NetTcpBinding(SecurityMode.None, true), "WCF");
host.Open();
Console.WriteLine("wcf service ready, port 11111");

//remoting server
RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off;

BinaryServerFormatterSinkProvider ssp = new BinaryServerFormatterSinkProvider();
ssp.TypeFilterLevel = TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider csp = new BinaryClientFormatterSinkProvider();

IDictionary props = new Dictionary<string, object>();
props["name"] = "tcpClientChannel";
props["port"] = "22222";

TcpChannel tcp = new TcpChannel(props, csp, ssp);
ChannelServices.RegisterChannel(tcp, false);
RemotingServices.Marshal(personServiceSingletonOjbect, "Remoting");

Console.WriteLine("remoting server ready, port 22222");

Console.ReadKey();
}
}
}

//PersonServer类
namespace PersonServer
{
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
class PersonServer : MarshalByRefObject, PersonService.IPersonService
{
public void ReceivePersonList(IList<PersonService.Person> personList)
{ return; }

public void Enter()
{ }

public void Leave()
{ }
}
}

==================================================
客户端主要代码:
==================================================
namespace PersonClient
{
class Program
{
static void Main(string[] args)
{
double totalMillionSeconds = 0;
Person person = new Person("test");
person.Age = 18;
person.Weight = 62.58;
person.Height = 1.75;
IList<Person> personList = new List<Person>();

Console.Write("please enter the server ip address:");
string serviceAddress = Console.ReadLine();

//test wcf service
PersonServerProxy wcfServer = new PersonServerProxy(serviceAddress);
wcfServer.Enter();

personList.Clear();
for (int i = 0; i < 500; i++)
{
double millionSecondsOneTime = SendPerson(wcfServer, personList).TotalMilliseconds;
if (i % 10 == 0)
Console.WriteLine("wcf 第{0}次传送耗时:{1} 毫秒", i, millionSecondsOneTime);

totalMillionSeconds += millionSecondsOneTime;
Thread.Sleep(200);
personList.Add(person);
}
wcfServer.Leave();

Console.WriteLine("wcf test complete");
Console.WriteLine("Total Milion seconds: {0}", totalMillionSeconds);
Console.WriteLine("Average Million seconds: {0}", totalMillionSeconds / 500);

//test remoting
totalMillionSeconds = 0;
IPersonService remotingServer = (IPersonService)Activator.GetObject(typeof(IPersonService), "tcp://" + serviceAddress + ":22222/Remoting");

personList.Clear();
for (int i = 0; i < 500; i++)
{
double millionSecondsOneTime = SendPerson(remotingServer, personList).TotalMilliseconds;
if (i % 10 == 0)
Console.WriteLine("remoting 第{0}次传送耗时:{1} 毫秒", i, millionSecondsOneTime);
totalMillionSeconds += millionSecondsOneTime;
Thread.Sleep(200);
personList.Add(person);
}

Console.WriteLine("remoting test complete");
Console.WriteLine("Total Milion seconds: {0}", totalMillionSeconds);
Console.WriteLine("Average Million seconds: {0}", totalMillionSeconds / 500);

Console.ReadKey();
}

static TimeSpan SendPerson(IPersonService server, IList<PersonService.Person> personList)
{
DateTime start = DateTime.Now;
server.ReceivePersonList(personList);
return DateTime.Now - start;
}
}
}
//客户端WCF Service 代理类:
namespace PersonClient
{
class PersonServerProxy : ClientBase<PersonService.IPersonService>, PersonService.IPersonService
{
public PersonServerProxy(string saddr)
: base(new NetTcpBinding(SecurityMode.None, true), new EndpointAddress("net.tcp://" + saddr + ":11111/WCF"))
{ }

public void ReceivePersonList(IList<PersonService.Person> personList)
{
base.Channel.ReceivePersonList(personList);
}

public void Enter()
{
base.Channel.Enter();
}

public void Leave()
{
base.Channel.Leave();
}
}
}




做这个例子做了一下午, 希望您能抽空指点一下 : ).
  回复  引用  查看    

#24楼 [楼主] 2008-03-26 19:12 张逸      

@Betree Xing
粗略看了一下,发现你没有附Remoting代码?在WCF的实现中,我发现你用了泛型集合!这可能是性能损耗的元凶!我想在你的Remoting代码中,应该没有该泛型集合吧?   回复  引用  查看    

#25楼  2008-03-26 19:43 Betree Xing      

吃过晚饭了吧,老大.真希望在您有空的时候能亲自写一个测试程序,为小弟们做个示范.

其中有一段是用来测试remoting的,您可能没有看到:

//test remoting
totalMillionSeconds = 0;
IPersonService remotingServer = (IPersonService)Activator.GetObject(typeof(IPersonService), "tcp://" + serviceAddress + ":22222/Remoting");

personList.Clear();
for (int i = 0; i < 500; i++)
{
double millionSecondsOneTime = SendPerson(remotingServer, personList).TotalMilliseconds;
if (i % 10 == 0)
Console.WriteLine("remoting 第{0}次传送耗时:{1} 毫秒", i, millionSecondsOneTime);
totalMillionSeconds += millionSecondsOneTime;
Thread.Sleep(200);
personList.Add(person);
}

Console.WriteLine("remoting test complete");
Console.WriteLine("Total Milion seconds: {0}", totalMillionSeconds);
Console.WriteLine("Average Million seconds: {0}", totalMillionSeconds / 500);
  回复  引用  查看    

#26楼  2008-03-26 19:47 Betree Xing      

.net remoting 的测试和wcf的测试是用的相同的服务契约(接口), 测试只用到了一个方法:

[OperationContract(IsInitiating = false, IsTerminating = false)]
void ReceivePersonList(IList<Person> personList);

wcf 和 remoting 都是用传递范型集合作为测试手段的   回复  引用  查看    

#27楼  2008-03-26 22:02 陈飞 [未注册用户]

@张逸
请教下,在wcf中使用泛型集合有问题吗?   回复  引用    

#28楼  2008-03-27 09:12 苹果非 [未注册用户]

@张逸

昨天下午我也准备去聊天室的,后来因为有事没有去成,真是遗憾啊,
问题我就方在这里问拉,

请问一下
WCF中.NET对象 最终转为化字节流是不是要经过2次序列化和一次编码呢
第一次序列化是.NET 对象到 MESSAGE对象
第二次序列化是.MESSAGE 对象到 XML Infoset(而这个XML Infoset包含3中形式(Binary;Text和MTOM)
最后 ,编码就是 XML Infoset到字节流(Byte Stream)过程,
不知道我说的对吗?
还有应用Binary形式为什么是最有效的呢,
也就是为什么消息的体积会变小呢   回复  引用    

#29楼 [楼主] 2008-03-27 14:03 张逸      

@Betree Xing
我争取有空做一下测试。

@苹果非
你说的步骤基本正确,不过说法有问题。从.NET对象到字节流,首先是消息交换,即.NET对象到Message对象,然后是序列化,如你说的,从Message对象到XML Infoset,这一步才是真正的序列化。最后一步是编码encoding过程,从InfoSet到字节流。

采用字节流的方式,对于传输速度而言,最高。但对场景的制约相对较大。   回复  引用  查看    

#30楼  2008-03-28 13:11 苹果非 [未注册用户]

@张逸
谢谢您的指点:
我之所以也称.NET 对象到 MESSAGE对象的过程为序列化,是因为在
<<Inside WCF>>一书中作者说到:
Chapter 5: Messages
Creating a Message

"Once a receiving application decodes and deserializes a Stream or Byte into a Message, it can then transform the contents of the Message into another object, or a graph of objects. This transformation is, for all practical purposes, another deserialization step."
也就是说Message into another object....another deserialization step.
那要反过来不就是serialization了.

还有我还是不明白您说的:"采用字节流的方式,对于传输速度而言"
因为无论采用的是Binary;Text或MTOM,结果不都是转化为字节流进行转播的嘛
为什么Binary的效率就是最高呢   回复  引用    

#31楼  2008-03-28 13:22 WCF群组博客      

@张逸

LZ能专门写一篇有关部门Binary;Text或MTOM他们的区别的文章,那该多好啊:)   回复  引用  查看    

导航

公告

logo.gif
我的著作与译作

《软件设计精要与模式》

《WCF服务编程》

MVP_Horizontal_BlueOnly.png

From 03-03-2006
Counter: site stats

与我联系

常用链接

我参加的小组

我参与的团队

随笔分类(244)

随笔档案(235)

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜