第零回.序和属性
第一回.真的了解.NET CF吗?
第二回.初窥CF类型加载器
第三回.让.NET CF CLR有条不紊
第四回.多窗体应用的性能与编程调试
第五回. WCF Mobile(Part 1)
摘要
对于Windows Mobile来说,WCF是一个崭新的概念,在.NET CF v3.5中提供了对WCF的支持,它是桌面WCF(Windows Communication Foundation,也称作Indigo)的一个子集。本文阐述了Compact WCF的功能和模型以及如何使用WCF轻松创建通信程序。
Keywords
Windows Mobile, WCF, .NET CF, Web Service, C#,Lunch Launcher
1. Compact WCF --全新的Mobile编程模型
WCF为那些需要用于通信的托管应用程序提供了一套新的统一的编程模型。它采用了一种可扩展信道的架构,使得应用程序能够工作在一个与传输介质和协议无关的“顶层”。WCF为开发者(尤其是那些分布式应用程序的开发者)提供了使用一套简单,稳定,易用的编程模型。使用WCF的编程模型,我们可以在应用程序中随意的收发信息,无论底层是用的HTTP,TCP还是Email进行通信。在大多数情况下,只需在初始化的阶段写下略有不同的代码,而通信逻辑层几乎不用改变就能满足您在不同信道上的通信需求。
下面这幅图展示了Compact WCF的基本架构
我们注意这里有个关键词Message,WCF的服务模型构建在这样的Messge对象上面。这样的一个Message对象以一种松散的形式描述了一个SOAP信封。它主要由两部分组成:消息体和一个可扩展的消息头集合。消息体是由应用程序定义的,而消息头是由对程序员相对透明的WCF的基础架构添加和处理的。这样的一个Message是WCF最核心也是最基本的组件。这就像经典的网络应用中,我们习惯以一个byte数组作为信息的基元一样。
用于移动设备的.NET Compact Framework 3.5 包含了WCF的一个子集,称作Compact WCF。运行在Windows Mobile设备上的WCF应用程序同样要遵循精简的原则。Microsoft的.NETCF团队最初对Compact WCF的预计是250kb的框架,他们做了大量的工作削减服务层以实现尽量精简的Message Stack。除了WCF的Message层面的东西,WCF for NETCF还包括了WS-Security的一个子集,这使得WCF for NETCF的框架达到了450kb。当然,最终版本的要比这个还要大一点,因为在这中间还集成了HTTP和Email的基础传输结构,还有文本编码器等组件,大是大了点,不过这些组件都是由可扩展的兼容性良好的框架支持。
Compact WCF 允许移动设备上的应用程序通过WCF服务与桌面PC机(服务器)进行交互。目前暂不支持在移动设备上直接发布服务,设备端的应用程序通常扮演的是发出服务请求的客户端的角色。在信道的绑定行为上,目前.NET CF3.5预定义的仅支持BasicHttpBinding和WindowsMobileMailBinding两种方式:
1) BasicHttpBinding,从本质上来讲,基本和原来调用Web Service的方式一样,因为它支持在http下进行传统的C/S互操作,客户端只需发出一个服务请求并等待回应。
2) WindowsMobileMailBinding,这是一个Compact WCF中全新的通信方式,它使用Email作为消息传输的载体,提供了一个全双工的通讯信道,允许进行非可靠的双向异步通信。
一个典型Compact WCF服务的应用场景如下:
一个货车司机M受雇于A公司,他持有一台运行着WCF客户端程序的移动设备。这个WCF的客户端程序注册了运行在A公司某台服务器上的一个WCF服务,用于及时获得客户提货的订单。当客户需要提货的时候,A公司通过WCF服务给M发送一个消息,M将货物送到客户那里。这里WCF服务是以一种非可靠的方式向M发出的提货消息,不管M的状态是怎样,不管他是否准备好。而在这个流程中,M也不必经常主动从服务器获取这些信息,这正是目前用得比较广的基于Web Service的模型。
WCF是一个层次化的协议栈,消息对象的格式和传输方式是相对独立的,这意味着你可以自定义这两个方面的组件,并添加到你的WCF应用程序中来。.NET Compact Framework团队正是利用了WCF的这种可扩展性,开发了独特的Email WCF消息模式。
2. Lunch Launcher—你必须知道的故事
关于Compact WCF,在它背后有一个Lunch Launcher(午餐发起者)的故事,这个故事直接导致了Email WCF的诞生。来自.NET Compact Framework团队的Roman Batoukov在他的文章:Windows Communication Foundation (Compact Edition) and the story of the Lunch Launcher 中提到了这个故事。大意如下:
.Net CF团队的伙计们喜欢去附近的一些当地的餐馆吃午餐(这当然要比Microsoft的露天茶座要好一些)。大家习惯叫上几个朋友一同去那些熟悉的餐馆,但是这样有一点比较麻烦,就是大家不好协调。因为大家不一定都待在各自的办公室里,有可能去了别的办公室甚至是另一栋办公楼,这就需要通过打电话,发email等手段联系。另外,大家对目的地也经常意见不一,每次得商量好一会儿。
而同时,.NET CF团队几乎所有人都有一部Windows Mobile的设备,可以接入Wifi网络或者各个运营商提供的网络。于是他们设想,如果有一个应用程序能实现这样的功能就好了:
某人通过移动设备发出一个午餐的邀请,这个邀请里面列出了一些备选的餐馆,然后大家投票决定去哪里吃饭。当投票完成的时候,投票产生的最终的目的地会反馈给每一个成员,然后大家一同去那个目的地就行了。恩,一个不错的想法。
(原文请查看http://www.blogs.msdn.com/romanbat,另外可以参考MVP黎波的这篇随笔)
不过这个想法有个很大的问题,就是各个设备的地址不好确定。通过移动运行商接入Internet的设备,被指派的IP地址是动态的,而通过WiFi连接的设备又经常因为NAT或者防火墙的缘故而不能直接访问到。所以在这样一些分散的移动设备之间建立一个稳定的连接是非常困难的。
我们再考虑这样一个更为实际的例子。一名员工在办公室里的时候,他持有的移动设备可能通过WiFi接入到Internet,当他走出办公楼,他的移动设备可能又切换到通过移动运营商提供的服务网络(如GPRS或者CDMA)。之后,这名员工可能又要进入另一栋办公楼,然后又介入了另一个WiFi网络。就在这个几分钟的行程中,他的移动设备的IP地址改变了三次。
像之前提到的“午餐发起者”这样的移动应用程序需要能将消息从一台设备发送到其他设备。这样看来,除非所有的移动设备使用VPN接入到你的本地网络或者稳定地接入到同一个WiFi共享网络,并且大家都使用静态IP,否则,想让你的应用程序总是能找到伙计们的移动设备是不可能实现的。不过还是有些办法可以解决确定设备地址的问题,只不过代价比较高,比如使用中间件技术或者设备每隔几分钟去连接服务器侦测是否已有消息处于等待装态。
然而,随着3年前Exchange Server2003 SP2和Messaging and Security Feature Update to Windows Mobile 5.0(a.k.a Adoption Kit Update 2)的发布,微软终于有了一种相对可靠的方式来确定公用网络环境下的移动设备的地址,那就是直推电子邮件(DirectPush e-mail)的技术。
Push e-mail之所以有效,是因为移动设备通过Microsoft IIS连接到Exchange Server,并通过IIS产生到Exchange Server的长连接(long-lived)HTTP请求。如果Exchange Server收到一个要发送到与某个移动设备匹配的Email地址的消息,它会以HTTP响应的形式将该消息直接发送给那台移动设备。如果之前建立的HTTP请求超时了,没关系,移动设备会再发起一个新的长连接请求。万一设备“掉线”了,还是没关系,Exchange Server扮演着一个存储与转发的角色,它会保留该条email消息,直到设备再次上线的时候再发送给它。这种移动设备与PC机通过Exchange Server通信的体系如图所示:
这种消息传输的模式被引入到了像“午餐发起者”(Lunch Launcher)这样的应用程序中来,为移动设备提供了一种相对稳定的定址方式(通过Email)。而“存储转发”的思想也被用于处理这种不稳定连接的设备通信问题。
3. Compact WCF中的邮件传输方式
有必要再多说说关于.NET CF中关于邮件传输的内容。.NET CF3.5中包含了WindowsMobileMailTransport来支持移动平台的通信,相对应的在桌面平台上使用ExchangeWebServiceMailTransport来进行移动设备和PC机的通信。
注意:ExchangeWebServiceMailTransport并不是单独存在于PC端的,它和WindowsMobileMailTransport都应当属于.NET CF3.5的组件,仅当安装了.NET CF3.5它才是可用的。
这两种传输方式相互作用使得PC机和移动设备之间,PC机之间,设备和设备之间能够畅通无阻的通信,而这些通信对于程序员来说都是透明的。前面已经提到了关于DirectPush的技术,就是说Exchange Server一旦收到信息就立即转发给监听对应信道名的设备,.NET CF中的邮件传输组件只有在一台支持DirectPush的Windows Mobile设备上才能充分发挥出它的威力。
(要了解更多的DirectPush和Microsoft Exchange信息,请看微软Exchange团队的这篇文章:msexchangeteam.com/archive/2004/04/26/120520.aspx)
如果您对MSMQ比较了解的话,那么.NET CF的邮件消息的传输也是非常好理解的,他们都是以类似的方式工作,只是MSMQ不需要考虑设备的定址问题。存储在设备和Exchange Server上的邮件扮演着消息队列的角色。每一台移动设备和服务器的邮件地址就是消息的URI。
(从理论上来说,在WindowsMobileMailTransport的传输方式下,两台移动设备可以通过任何支持SMTP/POP3的服务器来通信,但是目前在.NET CF3.5中仅限于使用Exchange Server 2007作为邮件服务器。暂时不支持以自定义的WinCE的设备做服务器。)
那么如何配置你的Mobile上的邮件开发环境呢?
首先请确保已经安装了Windows Mobile Devive Center 6.1或者ActiveSync® 4.5,你可以在这里下载:microsoft.com/activesync
如果您使用的是 Windows Vista®,打开你的Device Emulator Manager,连接上你的设备:
一旦同步成功,WMDC会提示你是否要进行一些设置,点击WMDC的“设置设备”:
然后在弹出的对话框中确保Email那一栏是被钩上的:
这个选项意味着你可以在你的设备应用程序中随时发送邮件了不管网络是否连上,一旦连上,邮件会立即发出。不用担心你设备上的的隐私问题, .NET Compact Framework 3.5邮件传输组件只会用到短信收件箱和邮件(你的WCF消息只能放在这两个文件夹中)。
(如果你的设备同步不成功,请在WMDC(或者ActiveSync4.5)中检查“连接设置”,确保“允许连接到以下任一端口”和“DMA”是选中的,如图:
)
4. Compact WCF支持的连接
就像前面提到的,WCF是一种层次化的体系结构,每一层都扮演着和其他层相对独立的角色。比如消息层(messaging layer)主要关注的是正确的消息格式,而传输层主要关心的是从一个节点到另一个节点的消息传输过程。从消息的层面来说,WCF基于一系列的Web Service的规范和协议(以WS开头的种种协议)。这些规范和协议都是有特定的工业标准的,以便不同厂商提供的各种Web Service的实现方式能够方便地进行互操作。
Compact WCF的消息层支持以下规范:
§ WS-Addressing
这一规范定义了一个消息头的标准格式以及一些相关信息(如目的地地址)
§ WS-Security
这一规范定义了一个消息是如何被加密的。它定义了数字签名是如何被用于收发双发的认证的。请注意,这些安全认证方式是独立于所用的消息传输方式的,所以安全认证总是能在各个不同的设备收发消息时得以正确工作。
§ WS-ReliableMessaging
顾名思义,这一规范主要关注的是要确保消息投递成功,即使是在不可靠的网络环境下。
我们知道,一个WCF服务提供了一个节点,由这个节点上的客户端发出服务请求。这样的一个节点通常由以下三部分的信息组成:
1) 服务所在地址
这里所说的地址的格式随着服务依赖的传输协议的不同而不同。例如,对于基于HTTP的服务来说,地址是我们熟悉的类似这样的格式:
http://www.freesc/WCFMobileService/WCFMobileService.svc
而对于新引入的存储转发的Email传输方式,则是像下面这样的格式: WCFMobileService@cnblogs.com/WCFMobileService.
2) 服务支持的绑定方式
服务的绑定方式描述了客户端是如何连接到服务的,并定义了服务所需要的数据格式。不同的绑定方式决定了传输协议的不同,消息编码方式的不同以及安全性方面的不同要求。
3) 服务实现的契约
这就是一组存放在.NET程序集里面的接口,并被标记为应用了[ServiceContract]特性。它定义了服务端能在该服务上调用哪些方法,换句话说,它决定了该服务支持那些操作。
(关于Compact WCF与完整版的WCF的不同请参考andrew arnottms的文章:The WCF subset supported by NetCF)
5. Why WCF?
正如在一开始那幅图中看到的,在WCF中,由Message维系着一个服务(Service)的概念(其实反过来说也成立),不错,这很像WebService,或者说这继承自WebService。那么对移动设备参与的应用程序来说,这样的服务有什么意义呢?
很显然,首先这些服务为设备应用程序节约了开发运行在设备上的相应服务的成本,这些服务的成本可以被最大限度的转移到设备所在网络的某台服务器上。通俗的说,就是各个移动设备可以访问该网络的某台服务器上的多个服务,这些服务都是由服务器在运行并维系的,移动设备本身无需安装专门的应用程序或者做任何怪异的配置。
其次,由于这些服务的代码集中在某台提供服务的机器上,只需更新该服务端代码而在客户端无需改动便可获得更新的服务。
另外,从性能上来说,对一些需要数据分析的移动应用程序,可以把某些大数据量,高密度的运算放到性能较好的PC机上,而移动设备只需通过WCF服务去获取一个结果即可。
在对Email的支持上,,WCF For .NETCF同样做的很出色,这尤其体现于Exchange Server的交互上,比如WCF Mobile可以利用ExchangeServer支持异步的可暂存的消息模式,用户即使离线也不妨碍消息的收发,因为ExchangeServer2007会保存消息,到用户上线的时候再送出,这种工作模式与Office家族的新贵Groove Server类似。
WCF让我们再次感受了封装的威力,它允许开发者构建可扩展的支持互操作的各种协议,并把这些协议结合起来。不过这里WCF本身不是本文要讨论的重点,本文假设您已经对WCF有了一些认识(可参考Programming WCF Services),当然,即使您对WCF不了解,相信您也能通过本文了解Compact WCF的功能和编程模型。
本文的下一部分将介绍如何使用Compact WCF的两种绑定方式在我们的应用程序中进行实际的开发。
推荐资源
- .NET Compact Framework Team blog
- .NET Compact Framework 3.5 Redistributable and Power Toys
- .NET CF相关博客
Enjoy!
©Freesc Huang
黄季冬<fox23>@HUST
2008/3/28