邱 玲,张立人,何海涛
(四川理工学院计算机学院,四川 自贡 643000)
Web服务提供了基于HTML的Web站点以外的快速、灵活的数据获取途径,然而,普通的Web服务只适合传输能被XML高效打包的数据类型,对于一些二进制数据,例如图形、图像、音频等,却难以高效传输,这严重限制了Web服务的应用领域。随着微软公司的SOAP扩展技术的引入[1],我们能对Web服务的全过程进行控制,从而具有传输任意数据类型的可能性。
Web服务作为一个跨平台获取数据的协议,必须屏蔽掉各种硬件平台和操作系统平台的差异。因此,Web服务必须提供以下几个方面的功能:一种独立于平台的数据交换格式、一种描述数据结构的方法、打包数据以跨越Internet传输的标准方法、Web服务通知客户程序自身结构的方法以及以编程方式定位Web服务的方法。为了实现这些功能,Web服务采用的技术分别是:使用XML进行数据的表达、用XML大纲进行数据结构的描述、以SOAP协议来打包数据并在Internet上传输、利用WSDL语言描述自身、以及采用UDDI进行定位[2-3]。
在这些基础技术中,我们着重考察数据的XML表达形式。XML是纯文本格式,但通过串行化和反串行化技术可以封装二进制数据。例如,一个整数1234,要发送出去时,串行化为文本“1234”,当对方收到这个文本后,又进行反串行化成为整数1234。由于文本格式对于任何平台都是可读的,所以XML就具有了跨平台传输数据的性质。但同时我们也注意到,串行化和反串行化是低效的,占用了大量的CPU时间,同时,用文本格式表达二进制将使用更多的字节,从而占用了更多的网络带宽。因此,这种基于串行化和反串行化的XML表达方式并不适用于复杂的数据类型。
Web服务的体系结构[4]是客户端/服务器形式,所以在工作中首先由客户端发起请求,然后由Web服务应答。由于这个过程是跨Internet进行的,要求穿越防火墙,所以将请求报文和应答报文都封装成SOAP报文形式,以HTTP协议进行发送,这样Web服务的工作过程实际就是客户端程序构造SOAP请求报文,其中以XML的形式串行化函数调用的名称和参数,然后将其以HTTP协议发送给Web服务端;Web服务端接收到请求报文后,对参数进行反串行化,完成函数调用,将计算结果重新串行化为XML形式,打包成SOAP应答报文,最后用HTTP协议发送回客户端;客户端收到应答报文后,对计算结果进行反串行化,从而得到实际的返回值,Web服务的一次工作过程完成。
在这个过程中,客户端程序只要发起了发送命令,就不能再进行任何操作,只能等待Web服务的应答。Web服务端同样如此,从接收到请求报文到发送应答报文都是Web服务器自动进行[5]。系统将自动进行相应的串行化、反串行化、SOAP报文的构造以及网络传输工作。整个过程都没有允许客户程序和Web服务进行更多的控制。
从以上讨论可以看出,由于XML串行化和反串行化的低效,同时Web服务没有允许我们对请求服务的全过程进行深入的控制,所以对于一些特殊类型的数据我们难以通过Web服务进行有效传输,例如图形、图像、音频以及含有复杂数据的对象等。这样就限制了Web服务的应用性。为了进行任意数据的高效传输,需要引入一种更深入的机制到Web服务标准中,这就是SOAP扩展。
SOAP扩展[6]的基本思想是将一个SOAP报文从发送到接收的整个过程划分为4个阶段,每个阶段都允许代码进行拦截和干预,从而控制对某些数据的串行化与否、数据的加密解密以及在SOAP报文中加入特定数据等。这4个阶段及其作用是:
(1)BeforeSerialize
串行化之前阶段,即对象串行化为SOAP报文之前阶段。此阶段拦截到的是二进制数据。对于客户端,这是在SOAP请求发送给Web服务之前,对于Web服务,这是在对Web方法调用的响应被返回客户端之前。
(2)AfterSerialize
串行化之后阶段,此时,对象已经串行化为SOAP报文,但还没有被发送出去。此阶段拦截到的是文本形式的SOAP报文。对于客户端和WEB服务,情形与BeforeSerialize相同。
(3)BeforeDeserialize
反串行化之前阶段,即已经接收到一个SOAP请求和应答报文,但还没有进行反串行化。此阶段拦截到的报文是文本形式。对于客户端,是从Web服务获得响应的时候,对于Web服务,是从客户端收到请求的时候。
(4)AfterDeserialize
反串行化之后阶段,这时,已经将接收到的SOAP报文反串行化了。此阶段拦截到的报文是二进制形式。对于客户端和Web服务,情形与BeforeDeserialize阶段相同。
这里,仅考虑高效传输大块二进制数据。SOAP扩展给了我们一种思路:既然我们想在SOAP报文中加入大块二进制数据而又不希望对这些数据进行例行的串行化和反串行化,那就应该在发送方已经经过串行化形成了文本形式的SOAP报文以后,而在发送出去以前,将大块二进制数据插入文本SOAP报文的某个位置;当接收方收到这个文本SOAP报文后,也应该在进行反串行化之前从那个位置取出大块二进制数据,并删除以还原SOAP报文的本来面目,再进行其他数据的反串行化。由于SOAP报文中的格式只对Web服务有效而对HTTP协议无效,所以我们插入大块二进制数据后不会影响SOAP报文在网络上的传输。因此,我们只要选择在发送方的AfterSerialize阶段和接收方的BeforeDeserialize阶段进行拦截并做相应处理即可实现大块二进制数据的传输。
首先从SoapExtension类派生出自己的扩展类,其中最重要的是重载ProcessMessage()方法。对于Web服务端,在这个方法中响应AfterSerialize阶段。下列关键代码表示了在原SOAP报文的某处插入一个图像文件:
FileStream fs=new FileStream("d:\old.jpg",
FileMode.Open,FileAccess.Read);
unsafe
{
long len=fs.Length;
byte*p=(byte*)&len;
for(int j=0;j<8;j++)
tempStream.WriteByte(*(p++));
}
Copy(fs,tempStream);
fs.Close();
对于客户程序,在ProcessMessage()方法中响应BeforeDeserialize阶段,从SOAP报文的约定字节处取出这个图像文件。从本例可见,通过SOAP扩展的方法可以很好地实现二进制数据的传输。
对于客户程序,在ProcessMessage()方法中响应BeforeDeserialize阶段,从SOAP报文的约定字节处取出这个图像文件。从本例可见,通过SOAP扩展的方法很好地实现了二进制数据的传输。。
[1] 冯柳平.基于SOAP扩展的Web服务安全机制研究[J].北京印刷学院学报,2009,17(6):37-39.
[2] Joseph Bustos,Karli Watson.NET Web服务入门经典[M].北京:清华大学出版社,2003.
[3] Russ Basiura,Mike Batongbacal,著.康 博,译.ASP.NET Web服务高级编程[M].北京:清华大学出版社,2002.
[4] 曾 岫,彭 宏,左国威.基于SOAP扩展的Web服务安全模型[J].广州航海高等专科学校学报,2008,16(2):40-42.
[5] 李林静,赵建伟.加强SOAP消息安全通信平台的分析及实现[J].计算机与数字工程,2011,39(3):92-97.
[6] 李林静,赵建伟.一种基于SOAP扩展的SOAP消息分析方法[J].计算机系统应用,2012,21(1):152-155.