Tuesday, November 10, 2009

理解SOAP

更多精彩请到 http://www.139ya.com


http://msdn.microsoft.com/zh-cn/library/ms995800%28classic%29.aspx


理解 SOAP
发布日期 : 4/1/2004 | 更新日期 : 4/1/2004

Aaron Skonnard

DevelopMentor

2003 年 3 月

适用于:

  • 全局 XML Web 服务结构 (GXA)

  • 远程过程调用 (RPC)

  • SOAP 1.1 和 SOAP 1.2 规范

  • 传输协议: TCP、HTTP、SMTP 和 MSMQ

  • Web Services Enhancements 1.0 SP1 for Microsoft .NET

  • XML 架构

摘要: SOAP 提供一种简单的、可扩展并且功能丰富的 XML 消息处理框架,用于定义高级别的应用程序协议,从而在分布式异构环境中提供更高的互操作性。(20 页打印页)

本页内容

简介 简介
SOAP 版本 SOAP 版本
消息处理框架 消息处理框架
扩展性 扩展性
处理模型 处理模型
协议绑定 协议绑定
HTTP 绑定 HTTP 绑定
RPC 和编码 RPC 和编码
SOAP 类型 SOAP 类型
小结 小结

简介

就在不久以前,SOAP 还不过是指肥皂而已。 而如今,大多数开发人员一听到这个词眼前就会浮现出一些尖括号来。 SOAP 最初代表“简单对象访问协议”。 如果在几年前问任何一个人 SOAP 的含义,他们很可能这样回答:“SOAP 是用来使 DCOM 和 Corba(例如,RPC 调用)在互联网上工作”。 原作者们也承认,在那时他们注重于“访问对象”,但随着时间的推移,人们希望 SOAP 能够处理更广泛的情况。 因此,SOAP 规范的重心很快从对象转移到通用的 XML 消息处理框架上。

这种重心的变化给 SOAP 缩写词中的 "O" 带来了一点小问题。 有意思的是,SOAP 1.2 工作组沿用了(到目前为止)SOAP 这个名称(为什么不呢?这个词太流行了),但决定不再把这个词拼出来以免误导开发人员。 如今,在最新的 SOAP 1.2 规范中,其正式的定义并不提及对象:

SOAP 是一种轻量级协议,用于在分散型、分布式环境中交换结构化信息。 SOAP 利用 XML 技术定义一种可扩展的消息处理框架,它提供了一种可通过多种底层协议进行交换的消息结构。 这种框架的设计思想是要独立于任何一种特定的编程模型和其他特定实现的语义。

这个定义确实体现了 SOAP 现在的主旨。 SOAP 定义了一种方法以便将 XML 消息从 A 点传送到 B 点(参见图 1)。 为此,它提供了一种基于 XML 且具有以下特性的消息处理框架:1) 可扩展,2) 可通过多种底层网络协议使用,3) 独立于编程模型。 以下将分别详细讨论这三种特性。

图 1. 简单的 SOAP 消息处理

首先,SOAP 可扩展性是关键所在。 在这个缩写词还代表某些含义时,"S" 意味着“简单”。 如果我们从 Web 中学到了一样东西,那就是,简单性总是比效率和纯技术更重要,因而互操作性成败的关键,就在于必须绝对要求简单性。 简单性仍然是 SOAP 的主要设计目标之一,这一点的例证就是 SOAP 缺少分布式系统的很多特性(如安全性、路由和可靠性等)。 SOAP 定义了一种通信框架,允许以分层扩展的形式随着时间推移而加入这些特性。 Microsoft、IBM 和其他软件厂商正在积极开发一个 SOAP 扩展的通用套件,该套件将加入大多数开发人员期待的特性。 这一计划被称为全局 XML Web 服务结构 (GXA)Microsoft 已经发布了针对若干 GXA 规范的一个参考实现,并将其命名为 Web Services Enhancements 1.0 SP1 for Microsoft .NET (WSE)

其次,SOAP 可在任何传输协议(诸如 TCP、HTTP、SMTP,甚至是 MSMQ)上使用(参见图 1)。 然而,为了保持互操作性,需要定义一些标准协议绑定以便草拟用于每种环境的规则。 SOAP 规范提供了一种用于定义任意协议绑定的灵活框架,并且由于 HTTP 的使用极为广泛,它现已为 HTTP 提供了一种显式绑定。

第三,SOAP 允许任何编程模型,并且不依赖于 RPC。 大多数开发人员立刻将 SOAP 与对分布式对象进行的 RPC 调用等效起来(因为 SOAP 最初就是关于“访问对象”的),但实际上,基本的 SOAP 模型更接近于传统的消息处理系统,如 MSMQ。 SOAP 定义了一种模型以便处理个别的单向消息。 你可以将多条消息组合成一条整体的消息交换。 图 1 说明了一种简单的单向消息,其中发送方不会收到响应。 但是,接收方可以向发送方发回一条响应(参见图 2)。 SOAP 允许使用任何数量的消息交换模式 (MEP),请求/响应只是其中一种。 其他示例包括要求/响应(与请求/响应相对)、通知和长期运行的点对点对话等。

图 2. 请求/响应消息交换模式

开发人员经常将请求/响应与 RPC 混为一谈,而实际上二者之间的差别很大。 RPC 使用请求/响应,但请求/响应不一定就是 RPC。 RPC 是 一种允许开发人员进行方法调用的编程模型。 RPC 需要将方法签名转换成 SOAP 消息。 鉴于 RPC 的广泛应用,SOAP 草拟了一项协议,以便将 RPC 用于 SOAP(参见本文稍后的RPC 和编码一节)。

具备这三种主要特性,SOAP 消息处理框架就促进了在异构环境中交换 XML 消息,而在这类环境中,互操作性长久以来都是极大的挑战。

SOAP 版本

从第一个发布的 SOAP 规范到如今被广泛实施的 SOAP 1.1,很多方面都发生了改变,从琐碎的细节到思想的重大转变。 SOAP 1.1 被提交给 W3C,并于 2000 年 5 月被发布为 Note。由于 SOAP 1.1 未能通过 W3C 过程的严格审核,"W3C Note" 状态使其还停留在仅是一个好主意的层次,但当完成时,它将最终达到“推荐”状态。 然而,由于如今 SOAP 1.1 得到了大小厂商如此广泛的支持,它仍然被认为是事实上的标准。

W3C 使用 SOAP 1.1 Note 作为新 XML 协议工作组的基础,负责产生下一版本的 SOAP,目前命名为SOAP 1.2。 SOAP 1.2 当前是一种“候选推荐方案”,意味着它正处在实施阶段且离最后完成为期不远。 一旦 SOAP 1.2 成为“推荐方案”,它极有可能很快获得厂商的支持。

在 SOAP 1.2 发布之后,为了提供向后兼容性,厂商应该继续支持 SOAP 1.1。 SOAP 版本控制基于 XML 命名空间。 SOAP 1.1 由 http://schemas.xmlsoap.org/soap/envelope/ 命名空间标识,而 SOAP 1.2 由 http://www.w3.org/2002/12/soap-envelope 命名空间标识(尽管当其成为推荐方案时,这也将改变)。

有关每个版本的命名空间名称和规范所在位置,请参见表 1。 在本文的剩余部分中,我们将讲述 SOAP 1.1 最重要的一些方面。 要了解两个版本之间完整的更改列表,请查看当前的 SOAP 1.2 规范。

表 1. SOAP 版本信息

  • SOAP 1.1

  • 命名空间名称

  • 规范位置

  • SOAP 1.2

  • 命名空间名称

  • 规范位置

消息处理框架

SOAP 规范的核心部分就是消息处理框架。 SOAP 消息处理框架定义了一整套 XML 元素,用以“封装”任意 XML 消息以便在系统之间传输。

该框架包括以下核心 XML 元素: Envelope、Header、Body 和 Fault,所有这些都来自 SOAP 1.1 中的 http://schemas.xmlsoap.org/soap/envelope/ 命名空间。 以下代码中提供了 SOAP 1.1 的完整 XML 架构定义,以供在阅读下文时参考。 我个人认为,每次让自己熟悉各种 XML 结构时,检查一下该架构是颇有帮助的。

SOAP 1.1 XML 架构定义

 xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"        
targetNamespace="http://schemas.xmlsoap.org/soap/envelope/"
>







maxOccurs="unbounded" processContents="lax" />

processContents="lax" />





maxOccurs="unbounded" processContents="lax" />

processContents="lax" />





maxOccurs="unbounded" processContents="lax" />

processContents="lax" />

















type="tns:encodingStyle" />









minOccurs="0" />
minOccurs="0" />





maxOccurs="unbounded" processContents="lax" />

processContents="lax" />



如果检查一下 EnvelopecomplexType 定义,你很快就能了解这些元素相互之间是如何关联的。 以下消息模板说明了 SOAP Envelope 的结构:

  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">







Envelope 元素始终是 SOAP 消息的根元素。 这就便于应用程序识别“SOAP 消息” — 只要检查一下根元素的名称即可。 通过检查 Envelope 元素的命名空间,应用程序也可确定所使用的 SOAP 版本。

Envelope 元素包含一个可选的 Header 元素(有关详细信息,参见可扩展性一节),后跟一个必要的 Body 元素。 Body 元素代表了该消息的有效内容。 它是一种通用容器,因为它可包含来自任何命名空间的任意数量的元素。 这就是试图发送数据的最终目的地。

例如,以下的 SOAP 消息代表了一个在银行帐户之间转帐的请求:

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">


22-342439
98-283843
100.00



如果接收方支持请求/响应,且能够成功地处理该消息,它应向最初的发送方返回另一条 SOAP 消息。 在这种情况下,响应信息也应包含在 Body 元素中,如下例所示:

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

xmlns:x="urn:examples-org:banking">


22-342439
33.45


98-283843
932.73





该消息处理框架还定义了一个名为Fault 的元素,用于在发生错误时在 Body 元素中表示错误。 这是不可缺少的,因为如果没有一种标准的错误表示方法,每个应用程序将不得不自己创建,从而使得通用基础结构不可能区分成功和失败。 以下示例 SOAP 消息中包含了一个 Fault 元素,指明在处理该请求时发生了“Insufficient Funds(资金不足)”错误:

 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">


soap:Server
Insufficient funds


22-342439
100.00
89.23





Fault 元素必须包含一个 faultcode,后跟一个 faultstring 元素。 faultcode 元素使用一种符合命名空间的名称对错误进行分类,而 faultstring 元素提供一种对错误可读的解释(类似于 HTTP 的工作方式)。 表 2 简要地说明了 SOAP 1.1 所定义的各种错误码(所有这些代码都包含在 http://schemas.xmlsoap.org/soap/envelope/ 命名空间中)。

Fault 元素也可能包含一个 detail 元素,以便提供该错误的细节,这样可以帮助客户端诊断问题,特别是在 Client 和 Server 错误码的情况下。

表 2. SOAP 1.1 错误码

名称

  • VersionMismatch

  • MustUnderstand

  • Client

  • Server

含义

  • 处理方发现 SOAP Envelope 元素的命名空间是无效的。

  • 处理方没有理解或服从 SOAP Header 元素的某个直接子元素,而该子元素包含一个值为 "1" 的 SOAP mustUnderstand 属性。

  • Client 类的错误表明消息的格式错误或者不包含适当的信息,因而不能成功。 这通常表明,如果不对该消息做出更改,就不应该重发该消息。

  • Server 类的错误表明该消息未能得到处理的原因与消息的内容并没有直接关系,而是跟该消息的处理有关。 例如,处理过程可能包括与某个上游处理器的通信,但该处理器没有响应。 如果在稍后重发,该消息可能会成功。

现在,假设你想在初始的消息中增加一些验证信息,以便接收方能够确定发送方是否有足够的权限来执行传输。 要达到这一目的,一种方法就是在主体中添加凭证信息,如下所示:

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">


22-342439
98-283843
100.00


dave
evad




如果使用这种方法,每项需要验证的操作都必须处理这些凭证。 这也意味着其他需要安全性的应用程序必须开发自己的解决方案以解决这个问题;归根结底,这将损害互操作性。 对于诸如安全性等公共需要,定义各方都同意的标准 SOAP 标头将更有意义。 然后,各厂商可以在其通用的 SOAP 基础结构中建立对扩展功能的支持,这样各方皆赢。 这种方法可提高开发人员的生产力,同时有助于确保更高级别的互操作性。 而这正是 SOAP 扩展性模型设计要实现的目标。

扩展性

大多数现有的协议都区分控制信息(例如,标头)和消息有效负载。 在这方面,SOAP 也不例外。 SOAP Header 和 Body 元素在易于处理的 XML 世界中也进行同样的区分。 除了易用性之外,可扩展 Envelope 的关键优势在于它可用于任何通讯协议。

在各种应用程序协议中(如 HTTP、SMTP 等)标头总是具有重要的意义,因为标头允许连网两端的应用程序就所支持命令的具体行为进行协商。 尽管 SOAP 规范本身并不定义任何内置的标头,标头将逐渐在 SOAP 中扮演同等重要的角色。 随着 GXA 日趋成熟及 SOAP 标头的标准化,开发人员能够更方便地定义丰富的应用程序协议,而不必每次都重新开始。

与 Body 元素类似,Header 元素是控制信息的通用容器。 其中可包含来自任何命名空间(除 SOAP 命名空间之外)的任意数量的元素。 放置在 Header 元素中的各个元素被称为标头块。 如同其他协议一样,标头块中包含的信息应该能够影响有效负载的处理。 因此,这里正适于放置诸如凭证一类的元素,以帮助控制对操作的访问:

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">



dave
evad




22-342439
98-283843
100.00



我们也可以利用一个名为 mustUnderstand 的全局 SOAP 属性对标头块进行标注,以指明接收方在处理该消息之前是否需要理解标头。 以下示例说明了如何要求对凭证标头进行处理:

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">


soap:mustUnderstand="1"
>
dave
evad


...

如果某个标头块被标注为 mustUnderstand="1",而接收方未设计为支持给定的标头,则不应处理该消息,而应该向发送方返回一条 Fault (带有 soap:MustUnderstand 状态码)。 如果 mustUnderstand="0" 或者没有提供 mustUnderstand 属性,则接收方可以忽略相应的标头块并继续进行处理。 在整个 SOAP 处理模块中,mustUnderstand 属性起着核心作用。

处理模型

SOAP 定义了一种处理模型,它大致规定了从 SOAP 发送方传输到 SOAP 接收方的过程中对 SOAP 消息的处理规则。 图 1说明了最简单的 SOAP 消息处理方案,其中一个应用程序(SOAP 发送方)向另一个应用程序(SOAP 接收方)发送一条 SOAP 消息。

但是,处理模型允许使用一些更有趣的结构(如图 3 中的结构),这类结构中包含多个中间 节点。 在下文中,将使用 SOAP 节点 这个术语指代任何要处理 SOAP 消息的应用程序,不管是最初的发送方、中间节点还是最终的接收方;否则,我将明确指出并使用相应的准确术语。

图 3. 高级 SOAP 消息处理

中间节点位于最初的发送方和最终的接收方之间,并截获 SOAP 消息。 中间节点可同时作为 SOAP 发送方和 SOAP 接收方。 中间节点使得有可能设计一些有趣且灵活的网络体系结构,而这些网络结构能受到的消息内容影响。 SOAP 路由就是一个很好的示例,它很大程度上利用了 SOAP 中间节点(有关 SOAP 路由的详细信息,请查看 Routing SOAP Messages with Web Services Enhancements 1.0)。

在处理消息时,SOAP 节点承担一个或者多个角色 (role),这些角色会影响如何处理 SOAP 标头。 各个角色被赋予独特的名称(以 URI 的形式),以便在处理过程中能够识别这些角色。 当 SOAP 节点接收到一条要处理的消息时,它首先必须确定要假定哪些角色。 它可以检查该 SOAP 消息以帮助确定。

一旦 SOAP 节点确定了要扮演的角色,它随后必须处理针对其角色之一的所有必要标头(标记为mustUnderstand="1" )。 SOAP 节点也可选择处理针对其角色之一的任何可选标头(标记为 mustUnderstand="0")。

SOAP 1.1 只定义了一个名为 http://schemas.xmlsoap.org/soap/actor/next 的角色(简写为 next)。 每个 SOAP 节点都必须承担 next 角色。 因此,当 SOAP 消息到达任一给定的 SOAP 节点时,该节点必须处理针对 next 角色的所有必要标头,它可以选择处理针对该 next 角色的可选标头。 除 next 外,SOAP 1.2 定义了另外一些角色(参见表 3),且应用程序也可以定义自定义角色。

SOAP 标头通过全局 actor 属性(在 SOAP 1.2 中该属性名为 role )来指定具体的角色。 如果不存在 actor 属性,则标头默认地指向最终的接收方。 以下 SOAP 消息说明了如何使用 actor:

 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

soap:actor="http://schemas.xmlsoap.org/soap/actor/next"
soap:mustUnderstand="1"
>
...

由于 wsrp:path 标头被指定为 next 角色且被标记为必要的 (mustUnderstand="1"),因此接收到此消息的第一个 SOAP 节点必须根据该标头块的规范来处理此消息,在这种情况下为 WS-Routing。 如果 SOAP 节点不理解针对其角色之一的某个必要的标头,则它必须产生一个带 soap:MustUnderstand 状态码的 SOAP 错误,并停止处理。 SOAP Fault 元素提供了faultactor 子元素,以指定在消息路径中哪个节点导致了该错误的发生。faultactor 属性的值是一个 URI,用以标识导致该错误的 SOAP 节点。

如果 SOAP 节点成功地处理了一个标头,则它必须从消息中删除该标头。 SOAP 节点可以再插入标头,但是这样做会改变合同方 — 它现在处于当前节点与该标头所指向的下一节点之间。 如果 SOAP 节点恰好是最终的接收方,则它还必须处理 SOAP 主体。

表 3. SOAP 1.2 角色

SOAP 角色名称

说明

  • 每个 SOAP 中间节点和最终的 SOAP 接收方必须 (MUST) 扮演此角色,并可以 (MAY) 另外承担零个或多个其他 SOAP 角色。

  • SOAP 节点绝不可以 (MUST NOT) 扮演此角色。

  • 要将某个 SOAP 节点确立为最终的接收方,该 SOAP 节点必须 (MUST) 扮演此角色。 SOAP 中间节点绝不能 (MUST NOT) 扮演此角色。

协议绑定

图 3中一个有趣之处是 SOAP 允许通过多种底层协议进行消息交换。 由于 SOAP 消息处理框架独立于底层协议,每个中间节点可以选择使用不同的通信协议而不会影响 SOAP 消息。 然而,为了确保各种 SOAP 应用程序和基础结构之间高级别的互操作性,标准的协议绑定是必要的。

一种具体的协议绑定准确地定义了应该如何利用给定的协议来传输 SOAP 消息。 换言之,它详细定义了 SOAP 如何适用于另一协议的范围,该协议很可能具有自己的消息处理框架以及多种标头。 协议绑定实际所定义的内容很大程度上取决于该协议的功能和选项。 例如,针对 TCP 的协议绑定应很大程度不同于针对 MSMQ 或针对 SMTP 的协议绑定。

SOAP 1.1 规范仅规范化了一种用于 HTTP 的协议绑定(由于 HTTP 的广泛使用)。 SOAP 已经用于 HTTP 之外的很多协议,但是其实现并未遵循标准化的绑定。 当你尝试与利用相同协议的其他 SOAP 实施进行集成时,只要准备好处理各种互操作性方面的问题,超前一点而不使用标准的协议绑定也未尝不可。

HTTP 绑定

HTTP 协议绑定定义了在 HTTP 上使用 SOAP 的规则。 SOAP 请求/响应自然地映射到 HTTP 请求/协议模型。 图 4 说明了 SOAP HTTP 绑定的很多细节。

图 4. SOAP HTTP 绑定

HTTP 请求和响应消息的 Content-Type 标头都必须设为 text/xml (在 SOAP 1.2 中是 application/soap+xml)。 对于请求消息,它必须使用 POST 作为动词,而 URI 应该识别 SOAP 处理器。 SOAP 规范还定义了一个名为 SOAPAction 的新 HTTP 标头,所有 SOAP HTTP 请求(即使是空的)都必须包含该标头。 SOAPAction 标头旨在表明该消息的意图。 对于 HTTP 响应,如果没有发生任何错误,它应该使用 200 状态码,如果包含 SOAP 错误,则应使用 500

RPC 和编码

尽管 SOAP 规范已日渐远离对象,它仍然定义了一种约定,以便利用上述的消息处理框架来封装并交换 RPC 调用。 定义一种标准的方法将 RPC 调用映射到 SOAP 消息,这使得在运行时基础结构可以在方法调用和 SOAP 消息之间自动转换,而不用围绕 Web 服务平台重新设计代码。

要利用 SOAP 进行方法调用,基础结构需要以下信息:

  • 1.终结点位置 (URI)

  • 2.方法名称

  • 3.参数名称/值

  • 4.可选的方法签名

  • 5.可选的标头数据

这些信息可以通过多种方法来传输,包括类型库、IDL 文件,或者,更好的是 WSDL 文件。 SOAP RPC 绑定定义了如何在 SOAP 主体中封装并表示这些信息。 为此,RPC 绑定首先定义如何将方法签名映射到简单的请求/响应结构,然后将这些结构以 XML 进行编码。 RPC 绑定规定将以一个按照方法命名的 struct 来模拟该方法调用。 该结构将包含对应于每个 [in][in/out] 参数的一个访问器,访问器的名称与参数名相同,其次序由消息签名确定。 方法响应也将作为一个结构来建模。 结构的名称无关紧要,尽管约定是使用方法名后跟 "Response"(例如,对于 add 操作,方法响应名应该相应为 addResponse)。 响应结构包含一个用于返回值的访问器(其名称在 SOAP 1.1 中无关紧要,但在 SOAP 1.2 必须是 rpc:result),其后是针对每个 [out][in/out] 参数的访问器。

让我们来看一个示例。 假设 add 操作具有以下的 C# 方法签名:

double add(ref double x, double y)

根据刚才所说明的 RPC 绑定规则,代表该方法调用的请求结构应如下建模:

struct add {
double x;
double y;
}

而响应结构如下:

struct addResponse {
double result;
double x;
}

现在的问题是: 应该如何将这些结构映射到 XML(R) SOAP 规范定义了一组编码规则,专门用于此用途。 SOAP 编码规则大致阐述了如何将当今最常用的数据结构(如结构和数组)映射到普通的 XML 格式。 根据 SOAP 编码规则,以上的请求结构应映射到以下 XML 消息(这将放在 SOAP 主体中):


33
44

且上述请求的响应消息将映射到以下 XML 消息(这个消息将进入响应消息的主体):


77
33

XML 架构的相关工作刚刚开始,SOAP 编码规则即已创立。 既然 XML 架构已经完成,开发人员可以简单地提供文字的 XML 架构定义,从而准确指定应该如何以 XML 来格式化请求/响应消息。 由于利用 XML 架构定义更易于获得互操作性,因此大多数开发人员已经决定完全摒弃 SOAP 编码规则。 实际上,自 SOAP 1.2 起,SOAP 规范不再正式要求支持 SOAP 编码规则。 从现在起,最好避免使用 SOAP 编码规则,有关此中原由的全面讨论,请查看关于 SOAP 编码的讨论一文。

尽管 SOAP RPC 绑定和编码规则为那些不愿意涉及诸如 XML 架构和 WSDL 等的应用程序提供了一个很好的 SOAP 集成层,因为 RPC 绑定和编码规则易于导致互操作性方面的问题,它们基本上已经失宠于 Web 服务社区。

SOAP 类型

要重申的是,如今有两种基本类型的 SOAP 消息处理: 文档和 RPC。 文档类型指出主体只是包含一个 XML 文档,而发送方和接收方都必须遵循该文档的格式。 另一方面,RPC 类型指出主体中包含某个方法调用的 XML 表示,正如刚才所述。

两种方法可用于确定如何将数据序列化到主体中: 使用文字的 XML 架构定义和使用 SOAP 编码规则。 利用前一种方法,架构定义逐字确定了主体的 XML 格式,不具有二义性。 然而,利用后一种方法,SOAP 处理器必须在运行时遍历各种 SOAP 编码规则以确定主体正确的序列化。 很显然,这种方法更易于导致错误和互操作性方面的问题。

最常见的情形是在使用文档类型时也使用文字架构定义(称为文档/文字),以及在使用 SOAP 编码规则时使用 RPC 类型(称为 rpc/编码)。 文档/编码和 rpc/文字也是可能的,但并不常见,也没有太大意义。 大多数 Web 服务平台都集中于文档/文字类型,将其作为发展的主要用例,且是现今 Microsoft ASP.NET WebMethod 框架的默认设置。

小结

SOAP 定义了一种简单而可扩展的 XML 消息处理框架,它可以通过多种协议用于各种不同的编程模型,尽管此规范中规范化了如何将 SOAP 用于 HTTP 和 RPC 调用。 SOAP 还定义了一个完整的处理模型,大致规定了当消息沿路径传送时如何对其进行处理。 总的来说,SOAP 提供了一个功能丰富而灵活的框架以便定义高级应用程序协议,这些协议可在分布式异构环境中提供更好的互操作性。

CVS SVN VSS 使用对比

更多精彩请到 http://www.139ya.com

From : http://www.cnblogs.com/liubiqu/archive/2009/01/05/1369533.html


版本控制系统里团队开发不免要用上CVS SVN VSS ClearCase等工具。至于选择上,则是根据开发团队搭建的平台,使用的编程语言相关联。



如果用.net平台开发,VSS无疑首选,尽管它曾经有不经时事的诟病,现在发展的功能也蛮强的。如果有服务器linux系统,则CVS,SVN都可以选择。现在SVN大有取代CVS之势。然而很多古老的程序员还是对CVS情有独钟。



如下节选一些网上的对比说明,我作以综述。当然,真正要弄懂这些版本控制系统,还是要花费巨大工夫学习研究,不可能在baidu或者google几下就能完成的。



一、Subversion包含绝大部分CVS功能



Subversion 作为CVS 的重写版和改进版,其目标就是作为一个更好的版本控制软件,取代目前流行的CVS。Subversion 的主要开发人员都是业界知名的CVS 专家。Subversion支持绝大部分的CVS 功能/命令;Subversion 的命令风格和界面也与CVS 非常接近。当然,不同的地方正是对CVS 的改进。



二、全局性的版本编号



一个新的版本,并得到一个自增量的版本号N+1,该版本号并不针对某个特定的文件,而是全局性的、针对整个版本库的。因此,我们可以将Subversion 的版本库看作是一个文件系统或文件目录树的数组。



从技术的角度来说,在Subversion 中,"文件foo.c 的第5 版本"这个说法是错误的;正确的说法应该是:"文件foo.c 在版本库被修改了5 次,即执行5 次commit 后是什么样子?"。显然,在Subversion 中,版本库被修改5 次后foo.c 的内容,和被修改了6 次后foo.c 的内容很可能完全一样,因为版本库的第6 次修改很可能只修改了版本库的其他部分,而并没有对foo.c 的进行修改。相反,在CVS 中,文件foo.c 的第1.1 版本和第1.2 版本总是不同的。



Subversion 的全局性版本编号为Subversion 带来了诸多的优势:如对目录或文件执行拷贝,无论涉及多少文件,Subversion 不需要对单个文件依次执行拷贝命令,仅仅需要建立一个指向相应的全局版本号的一个指针即可。



三、目录的版本控制



CVS 只能对文件进行版本控制,不能对目录进行版本控制,因此CVS 没有任何关于文件"移动"(move)操作的概念。当人为进行文件移动操作时,CVS 只能注意到,一个文件在一个位置被删除了,而在一个新位置创建了另外一个文件。由于它不会连接两个操作,因此也很容易使文件历史轨迹丢失。设置 CVS 存储库时,必须非常谨慎地为每个文件选择准确的位置,因为在设置之后,几乎就要一直使用这个位置了。



同样由于CVS 不记录目录的版本历史,CVS 不支持对文件的"重命名"(rename),人为的对文件进行重命名会使得命名前后的文件失去历史联系,而记录历史本来是版本管理的主要目的。



还有,CVS 不支持对文件的"拷贝"(copy),人为的拷贝对CVS 而言,只能看到新的文件的增加,而不能记录拷贝源文件和目标文件之间的联系。



综上所述,缺乏对文件"移动"、"重命名"、"拷贝"的支持的根源在于CVS 不能记录目录的版本历史,而这些操作在当前的软件开发过程中经常发生,这正是Subversion被开发并取代CVS 的主要原因之一。



Subversion 将目录作为一类特殊的文件来处理(事实上,从文件系统的角度来看,目录确实是一类特殊的文件,当目录中的子目录/文件被删除、重命名、或新的子目录/文件被创建时,目录的内容将发生改变)。因此,Subversion 象记录普通文件的修改历史一样记录对目录的修改历史,当发生文件/目录的移动、重命名或拷贝操作时,Subversion 能够准确记录操作前后的历史联系。同样,象对文件的不同历史版本进行比较一样,Subversion支持对目录的不同历史版本的比较,清晰展现目录的变化历史。



四、原子性提交



从使用者的角度来看,CVS 和Subversion 都支持对多个文件修改的批量提交,但二者在实现方式上存在本质的区别。



CVS 采用线性、串行的批量提交,即依次地,一个接一个地执行提交,每成功提交一个文件,该文件的一个新的版本即被记录到版本库中,提交时用户提供的日志信息被重复地存储到每一个被修改的文件的版本历史中。



CVS 串行批量提交模式的弊端在于-当任何原因造成批量操作的中断时(典型原因包括:网络中断、客户端死机等),版本库往往处于一个不一致的状态:原本应该全部入库的文件只有一部分入库,很有可能版本库中的最新版本不能顺利编译,更为严重的是,随着其他的用户执行cvs update 操作,该不一致性将迅速在开发团队中扩散,从而严重影响团队的开发效率,并存在质量隐患。另外,假如该批量提交的中断没有被及时发现,开发团队往往要花更多的时间进行软件调试和排错。



CVS 即使在批量提交不发生中断时也会造成不一致:假设用户A 启动一个需要较长时间才能完成的批量提交;与此同时,用户B 执行cvs update 操作。此时,用户B 很有可能得到一个不一致的更新,即用户B 通过"更新"操作,得到用户A 的部分修改文件。



Subversion 彻底消除了CVS 的以上弊端。无论批量提交包含多少文件修改,只有当全部文件修改都成功入库,该提交才变得有效,才对其他用户可见;否则,无论任何原因造成中断,Subversion 都会自动执行"回滚"(rollback)操作。换一个说法,Subversion 保证所有的修改要么全部入库生效,要么一个也不入库,即对版本库不作任何的修改。这就是Subversion 的原子性提交(atomic commit)。



由于Subversion 的原子性提交特性和全局版本编号方式,当提交成功完成时,一个唯一的、新的全局版本编号产生,而提交时用户提供的日志信息与该新的版本编号关联,只进行一次存储(区别于CVS 的按文件重复存储)。



五、支持变更集概念



由于Subversion 的所有提交是原子性的,每次成功提交形成的唯一的全局版本号对应此次批量提交的所有文件修改,也就是说,一个Subversion 版本号其实对应了一个逻辑上的变更集(change set),该变更集可能对应于对一个BUG 的修复,或者对应于对一个已有功能的改进,或者对应于一个新功能的实现。可以说,变更集是一个软件开发活动的逻辑结果,该变更集可以通过其对应的版本号在软件开发的其他过程中(如软件合并/集成过程,软件发布管理,变更管理系统,缺陷追踪系统)被引用。因此,Subversion 将版本管理从单纯的、单个的文件修改的层次通过逻辑上的抽象,上升到更便于理解和交流的开发活动的层次。



六、差异化的二进制文件处理



由于历史原因,CVS 主要是为早期的程序员设计的,CVS 能够有效处理文本文件(或ASCII文件,源代码文件),可以对文本文件进行差异化的存储、新旧版本的比较,文件合并等;但对于二进制文件,CVS则明显力不从心。在CVS 的版本库中,对于二进制文件的历史版本,CVS 唯一能做的就是对不同的版本进行独立的、冗余的存储,哪怕版本之间其实只存在微小的差异。举例而言,一个10M 的二进制文件(照片、图形文件、机械设计文件、电子设计文件)假如每周修改一次,无论每次修改的大小,一年下来,仅该文件就要消耗500M 以上的存储空间。而且,客户端每次获取该文件的新版本都要消耗10M 的网络流量。



对于目前的开发团队,无论是软件开发,Web 站点的开发,手机等电子产品的研发,需要进行版本管理的不仅是源代码等文本文件,还需要管理需求文档、设计文档、测试文档、用户手册,图形图像文件,机械/电子设计文件等诸多的二进制文件,CVS 显然不是一个好的选择。



与CVS 不同,Subversion 采用统一的二进制差异算法(binary differencing algorithm),即对文本文件和二进制文件采用相同的差异比较算法,并以相同的方式在版本库中进行存储:每次提交后版本库中只存储相对于先前版本的差异,从而可以节省大量的存储空间。



该二进制差异算法不仅应用在版本的存储上,更为重要的是,Subversion 对二进制文件与文本文件一视同仁,当客户端需要获取新的版本时(如执行svn update),在网络上只有版本的差异被传输,从而大大减少对网络带宽的消耗。更多细节参见"七、双向的差异化-压缩网络传输"。



七、 双向的差异化-压缩网络传输



如上所述,CVS 对二进制文件不能进行有效的差异化处理。对于文本文件,CVS 仅仅支持单向的差异化传输:从CVS 到客户端的传输是差异化的,即执行cvs update 时,只有差异的部分从服务器传输到客户端;而当执行cvs commit 时,无论代码变化多少,CVS 都需要从客户端向服务器完整传输被修改文件的全部内容,不能只传输差异。



相反,无论是文本文件还是二进制文件,Subversion 都进行双向的差异化传输,并且差异化内容还要进行压缩/解压缩的过程:在服务器端获取差异显而易见,与CVS 类似;Subversion 在客户端获取差异的秘密在于 — Subversion 在客户端的工作拷贝中隐含了每个文件的一个"只读的、干净的"副本(该副本隐藏在隐含目录.svn 里,通常不可见,该副本还有更多的妙用,参见"十二、更多的本地/离线操作"),通过比较用户在客户端的修改和该隐含的副本,Subversion 获取需要真正传送到服务器的差异,并对差异进行压缩后才进行网络传输。



对CVS 而言,操作的成本(网络带宽消耗是最大的操作成本)与被修改的文件的大小成比例,而与修改本身的大小无关;对Subversion 而言,操作成本只与修改本身的大小成比例,而与被修改的文件的大小无关。因此,与CVS 相比,Subversion 消耗更少的网络带宽(以客户端的存储空间换取更少的带宽消耗在目前的计算环境下应该是个相当不错的选择!)。Subversion 更加适合基于互联网(或广域网)进行协作开发的地理上分布的团队 — 版本服务器集中、单一;客户端广泛分布。



八、高效、快捷创建分支和基线



CVS 和Subversion 都支持分支(branch)和基线(tag),通过分支与合并,可以有效支持大项目的并行开发模式;通过基线管理,可以准确标识一组文件的版本,有效进行软件发布管理和必要时的历史回溯。



但CVS 和Subversion 在实现分支和基线的方式上存在很大的不同。CVS 在创建分支的时候,需要对所有进行分支的文件进行依次的操作,因此分支的建立成本(主要是建立分支所需的时间,或消耗的计算资源)与参与分支的文件数量成比例,项目越大,版本库越大,文件越多,分支的建立成本越高;基线(tag)的建立与此类似。



Subversion 的分支和基线是通过执行"拷贝"来建立的:回想一下在没有引入版本管理工具的时候我们是如何进行所谓的"分支"和"基线"管理的?答案显然是"拷贝" — 我们通过"拷贝"或"备份"来建立基线;同样,为支持多个开发人员可以同时进行开发,我们为每个开发人员创建一份"拷贝"。由此看来,Subversion 通过"拷贝"来建立分支和基线显得非常自然,有点"返朴归真"的意思。



由于Subversion 的全局版本号特性,Subversion 中分支或基线的创建过程,或Subversion中的"拷贝"过程,真正的操作是在版本库中创建一个到某一全局版本号的指针(pointer),不再需要针对众多的单个文件依次执行操作。因此,该操作的成本为一个很小的常数,与项目大小,版本库大小,文件数目的多少无关;并且,分支或基线的建立不需要进行版本的冗余存储,新建立的分支或基线基本不占用版本库空间,分支的后续存储空间的开销也只与修改的大小有关。



九、集成Apache Web Server,提供更多的特性



Subversion 通过与Apache Web Server 的集成,可以提供基于http/https 协议的版本库访问机制,从而支持Subversion 跨越防火墙的安全访问。除此以外,Subversion 还可以利用更多的Apache 特性,包括但不限于:Apache 丰富的用户认证机制(包括通过LDAP服务器如Windows Active Directory 服务器的用户认证),基于目录路径的精细粒度的访问控制,对传输的网络流量进行压缩/解压缩,浏览版本库目录结构等等。



十、支持WebDAV

WebDAV(Web-based Distributed Authoring and Versioning)是一种基于 HTTP 1.1 协议的通信协议.它扩展了HTTP 1.1,在GET、POST、HEAD 等几个HTTP 标准方法以外添加了一些新的方法,使应用程序可直接对Web Server 直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。

Microsoft windows2000/XP 及IE, Office 还有Adobe/MicroMedia 的DW 等都支持WebDAV,这又大大增强了Web 应用的价值,以及效能。对于需要大量发布内容的用户而言,应用WebDAV 可以降低对CMS 系统的依赖,而且能够更自由的进行创作。上传、下载变得轻松自如。

Subversion 通过与Apache Web Server 的集成,支持WebDAV 协议,使得业务用户(business users)或非技术用户在不安装任何版本管理客户端的情况下轻松访问Subversion 版本库,不改变业务用户已有使用习惯,支持分布的业务用户对文档的评审、修改并实现版本控制,真正将软件开发的生命周期从开发/技术团队扩展到项目的全部干系人(stakeholder),避免通过电子邮件传递文档的混乱与无序、通过Windows 操作系统共享造成的安全漏洞、病毒攻击、历史版本被覆盖或丢失、审计困难等诸多典型问题。



十一、更好的冲突标识与处理



CVS 和Subversion 都支持通过分支与合并进行并行开发,并可以自动检测到合并时的冲突(conflicts),并在合并结果中以<<<<<< … >>>>>>标识合并的冲突部分。

在CVS 中,经常会出现由于用户的疏忽(如,没有注意到冲突,或没有完全处理好冲突)而将仍然带有<<<<<< … >>>>>>冲突标识符号的文件直接进行提交(commit),从而在版本库中产生垃圾版本。

Subversion 有效解决了CVS 的以上问题:Subversion 记录并保持文件的冲突状态,只有当用户明确执行svn resolved 命令后,该冲突状态标识才被复位,该文件才能被提交,从而大大减少了将仍然带有<<<<<< … >>>>>>冲突标识符号的文件直接进行提交的可能性。



十二、 更多的本地/离线操作



众所周知,CVS 客户端的工作拷贝中包含了一个隐含目录CVS,该目录中记录了客户端需要的一些管理信息;与此类似,Subversion 的客户端工作拷贝中也包含了一个隐含目录.svn,该目录中同样记录了客户端需要的一些管理信息,如版本库URL,当前访问版本号等。

与CVS 不同的是,Subversion 的.svn 目录中还包含了工作拷贝中每一个文件的一个"只读的、干净的"副本。正是由于该副本的存在,使得Subversion 与CVS 相比,可以执行更多的本地/离线操作,即某些操作不需要访问版本库服务器,因此不需要存在从客户端到服务器的网络链接,当然也不消耗任何网络带宽,这进一步增强了Subversion 对广域网的友好支持。

Subversion 的以下命令可以进行离线操作:

svn status - 显示工作拷贝上的本地修改概况;

svn diff -显示工作拷贝上的本地修改细节,比较修改前后的内容;

svn revert - 撤销工作拷贝上的本地修改;



十三、 对符号链接进行版本管理



在Unix 文件系统中,符号链接(symbolic links,包括硬链接和软链接)是一种重要的文件系统元素。CVS 不能对符号链接进行版本管理;Subversion 则可以对符号链接进行版本管理。



十四、 元数据管理



与CVS 相比,Subversion 增加了元数据(metadata)管理机制。即可以对版本库中的文件或目录附加任意的"属性"(property),并记录属性的变化历史,也就是对元数据进行版本管理。一个Subversion 属性是一个"属性名称/属性值"的二元组,如"BugNumber= 100"就是一个属性,可以将该属性附加到版本N 上,以说明版本N 改正了编号为100的BUG。

Subversion 元数据的目的是提供附件的信息以满足流程或过程自动化的需要,以增强Subversion 的管理能力和自动化程度。Subversion 自身就通过"属性"来存储一些特殊的信息。一个使用Subversion 元数据的例子:可以在一些批处理的脚本程序或Subversion的钩子程序(hooks)中创建、访问、修改"属性"元数据来满足流程自动化的要求。

十五 VSS CVS 比较

VSS适合小团队使用,基本的配置管理功能都有。VSS最大的特点就是部署比较简单,上手比较快。VSS最大的缺点就是安全性问题,目录共享、文件方式存储等。当然VSS还只能在Windows下使用。

CVS了解过,应该说特点也很鲜明。首先CVS是开源软件,根据长期的流传,已经演变了很多版本,适合于不同的平台。因此,在CVS客户端上是多种多样的。其次,CVS的部署稍微复杂点,现对VSS来说,这是其一缺点。最后,CVS在配置管理的理念上,比VSS有所进步。

十六 Vss与Svn 的对比

1. SVN支持重命名,这对 Java开发来说非常重要。

为了得到更好的代码,开发中需要经常进行重构,重构就经常涉及到文件的重构名,而重命名中 VSS 中是不被支持的。

2. 开发的时候不一定要锁定。

一方面导致重构不方便,另一方面,不能离线开发,使用 SVN 就不同,可以带回家继续开发,回来后,提交就行了。

3. 多平台。
可以支持多个平台下的操作


4. 更好的客户端支持。
Eclipse 中的 VSS Plugin 不如它的 SVN Plugin 好用。一个在 Windows 下用的 SVN 客户端 TortoiseSVN 也比 VSS 的客户端好用(VSS 只有微软提供的一个 GUI 客户端)。

5. 更好地与外围工具集成。

各种各样的外围工具(主要是服务器端),满足多种需要。如果有需要,也可以自己写插件或管理脚本,开放的架构,允许我们这样做。

6. 方便。

一个例子:部署应用的时候,以前的做法是找出一个项目中修改过的文件,更新到服务器上去,现在可以在服务器上执行 svn export 命令,把代码库中的最新版本导出,完成部署(也可以替换回老版本)。

7. 速度与稳定性看起来都不错。
学习它的管理、它的工作方式,是值得的。而 VSS 是一个已经被逐渐抛弃的软件。如果时间不是多得没处用,那么就把时间花在最值得花的东西上面。

Tuesday, October 27, 2009

POSIX thread (pthread) libraries

更多精彩请到 http://www.139ya.com

POSIX thread (pthread) libraries http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html


http://en.wikipedia.org/wiki/POSIX_Threads

又切了个脂肪瘤

更多精彩请到 http://www.139ya.com


左臂上部这个瘤瘤实在有些麻烦,不管走着坐着都经常碰着,还是下决心一切了之。这次约在北京医院,主要是想着人不多。结果今天下午去的时候发现人还真的不多,约的是14:00,到那儿一看大夫比病号多,直接被引进手术室,眼见着一个比我还高的男大夫指着手术台,对我低吼道:“就躺那儿吧”,我打眼一看,4、5个学生摸样的小大夫眼巴巴的望着我,看样子是有日子没实习了。。。

手术比较顺利,10分钟左右就完事儿了,麻药也很见效,开刀缝针包扎都没啥感觉。大夫在给我做手术的同时也在向周围围观的同学讲解:"像这种脂肪瘤手术,我们就不能割梭形的切口...",“这么大的口子,我们要尽量的少缝几针,不要给患者留下大疤...”,“四肢的手术拆线时间是最长的,要10到14天左右...”,周围的同学们都小声附和着,看样子受益匪浅。

20分钟左右我就下床了,还好,不疼,周围的同学们也都貌似比较感激的望着我,多少有些欣慰吧...

英语学习网站!

更多精彩请到 http://www.139ya.com

1、 练习听力

美国国家公共广播电台 NPR ( 请大家在百度搜索 "npr" ,搜索结果的首条就是 NPR ) 。

特点:标准美式英语。
建议:每天花三十分钟左右,反复听英语广播,这是听力过关的必经之路。点击网页中左边“ BROWSE TOPICS ”下面的“ News ”选项。选择自己有兴趣的新闻链接,点开“ Listen Now ”左边的红色小喇叭图标,然后反复听该新闻的广播。


英国广播公司新闻频道 BBC ( 请大家在百度搜索 "news.bbc" ,搜索结果的首条就是 BBC ) 。
特点:标准英式英语。

建议:点击网页中左边选项中的“ Video and Audio ”,再选择视频短片。



2 、练习阅读
路透社 ( 请大家在百度搜索 "reuters, news" ,搜索结果的首条就是 路透社网 ) 。

特点:内容丰富、全面。文章都为标准英语,多阅读对于写作也很有帮助。
建议:每天花二十分钟左右,选一篇自己有兴趣的文章阅读,以泛读为主。对于生词的发音,可以用韦伯字典网站查发音。对于不懂的词汇和句子,可以用 Google 英译中来翻译。


3 、词汇记忆

我要模考网词汇练习 ( 请大家在百度搜索 " 我要模考网 " ,搜索结果的首条就是 我要模考网 ) 。

特点:在线词汇练习,不枯燥,效率高,在答案页面上还可以听单词发音。
建议:每天花十分钟左右,选一组词汇,反复练习,直到做到全对为止。对于发音没把握的单词,在对答案时要记得查听一下该单词的发音。放松心情,把练习当作游戏来做可能效率会更高。



4 、单词发音

韦伯字典 ( 请大家在百度搜索 " merriam-webster " ,搜索结果的首条就是 韦伯字典网 ) 。

特点:世界权威词典,发音绝对标准,对于纠正发音很有帮助。
建议:在网页中间的输入框中输入你要听发音的单词,然后点击“ Search ”,在搜索结果页面上再点击单词旁边的红色小喇叭图标就可以听到发音了。


5 、翻译

Google 翻译网 ( 请大家在百度搜索 " Google 翻译网 " ,搜索结果的首条就是 Google 翻译网 ) 。

特点:方便,实用。单词、句子都可以翻译。
建议:主要用来翻译单词、词组、和短句。长句的翻译有时候可能不太准确,需要加以分析和判别。


原版英语小说网
http://www.en8848.com.cn/

T43 2668 BH4 vs iDeneb 1.5.1 OSX 10.5.7

更多精彩请到 http://www.139ya.com


t43 2668BH4

http://www.memac.cn/read-mac-tid-3089.html


⁃ Chameleon v2 RC2
⁃ PS2FixMouse
⁃ PS2FixKeyboard
⁃ VoodooPS2Controller Remove
⁃ VoodooPS2Trackpad

⁃ CPUS=1 Fix
⁃ Firewire Remove
⁃ BatteryManager
⁃ VoodooPower
⁃ VoodooPower ( Kext )
⁃ GenericCPUPMControl ( App )
⁃ VoodooUSBEHCI
⁃ 9.2.0 Sleep ( Intel/AMD SSE2/SSE3 )

⁃ AC97Audio

⁃ ICHx Fixed ( ICH10 Support )