2007年01月10日

网第排名挑战Alexa权威
更新日期:2007-01-10

来源:世界网络 作者:全风

网站排名一直以来就是Alexa的“专利”,然而这种局面正悄悄地被国内的一个网第排名改变。根据网第网站(www.wondi.cn)公布的信息,网第定位在全球中文网站排名,将服务于中国以及所有华文网站。

通过查询第三方提供的网站流量数据可以了解一个网站的运行情况,这对于网站经营者、广告商、投资机构都是一个不可缺少的重要指标。由于过去一直只有Alexa提供所有网站的排名分析数据,Alexa排名成了所有网站经营者的一个答卷评价,这对于大多数中文网站的经营者并不公平。这主要有以下原因:

一是Alexa对中国的网民不够亲和。Alexa排名数据所依赖的Alexa工具条没有中文版本,这对于Alexa工具条在中国的应用推广有很大的限制。Alexa工具条安装率在普通中文上网用户中安装率低。

二是Alexa提供的排名数据有偏差。由于Alexa工具条功能单一,中文网站用户中安装Alexa工具条的大部分限于网站排名的需要,而最广大的网络用户的数据并没有得到公平对待。在Alexa排名,一个礼品购物网站和一个IT网站的Alexa排名不具备可比性。

三是Alexa作弊严重。在数据识别、数据抽取、异常数据等处理过程中,Alexa没有一套应对网站作弊行之有效的方法。只要交付一定的费用,“排名专家”就可以轻松地决定网站的排名。

克服以上问题,提供公平、公正的网站排名及分析数据,也同样是网第排名必须面对的问题。网第网站公布,网第排名的数据基础是在联合了中国诸多门户网站、行业网站、个人网站的基础上,其统计方法和Alexa有些类似。从网第网站查询的数据结果来看,其访问数据分析已经涵括了2006年6月份以来的访问分析数据,给出的排名、访问量、浏览量等网站运行指标和子网站运行指标图文并茂。在整体界面表达和使用方式上,比Alexa更加贴身于中国网民使用。

作为中国本土的新生代网站排名,如若真能克服用户数偏低、行业及地区差异、网站作弊等Alexa排名存在的问题,并能在中国互联网环境中保持其特有的公平、公正性,将在成为中国下一个互联网行业的标准。

2007年01月09日

距离那个所谓的中国互联网协会推出的“中国互联网排名”不到一个月,深圳又出现一个“中国互联网排名”产品 http://www.wondi.cn ,比以前的那个稍微有点特色,看来2007年命中了是个网络排名年啊。

2006年12月21日

12月19日,由中国互联网协议主办的http://www.chinarank.org.cn中国网站排名的公布,看了实在值得怀疑,
不清楚其排名的数据源从那里来,本人试着下载了他们的工具条看看,发现其做的真够烂,如果他们是靠这个来收集分析数据,那就更觉得可笑了,他们的这个工具条安装数量多少了,现在的分析数据完全是凭空在想象,不可信!

2006年11月23日

这年头很多女演员为了上戏,都和导演睡觉。娱乐圈“性丑闻”似乎也早就不是新鲜事,而张钰事件更是将这种“潜规则”展现在大众面前。金钱与肉体的交换,名与利的追逐,在这个圈子里真的那样赤裸裸吗?繁华热闹的“艺术”背后,到底藏了多少不可见人的肮脏呢…...[

见怪不怪!

黄健翔辞职相当与地震了。这两天各种消息很多,可真正原因是啥?为了让朋友看清来龙去脉,笔者费好大劲搜索以下东西,慢慢看吧,呵呵。从黄健翔写给领导的解释文字里看,这封信是S某执笔。刊登如下,同时也找到黄健翔逐一回驳的原始文字。以下文字谢绝一切媒体转载,否则将追究转载者责任并文责自负。谢谢合作。
 

关于黄健翔同志的情况说明及意见

 

J主任并有关领导:

体育频道评论员黄健翔同志近期内,违反台播音员主持人相关管理规定,频繁参加各类社会活动。按照台里及频道的相关规定,台里的主持人在参加与台里无关的社会活动之前必须向相关部门申报,得到批准后方可参加,而黄健翔同志则未能执行台里的社会活动报批程序,在一定范围内造成了不良影响。现将黄健翔同志近期内未经批准参加的社会活动呈报如下:

1、        2006年8月开始,参加《时尚》杂志“时尚先生”的评选活动并出席相关仪式。

2、        2006年10月,与TOM网站合作,组织“黄健翔进校园系列活动”,并于10月18日在清华大学进行了演讲。据统计,这是TOM网与黄健翔合作以来的第六期走进高校演讲活动。此项活动现仍在持续。

3、        2006年10月29日,出席第15届金鸡百花电影节并担任主持人。

4、        据《北京电视报》报道,本周四,即2006年11月2日,黄健翔还将参加由郭德刚担纲的德云社十周年庆典活动。报道中还称:届时,黄健翔将与足球记者董路合说一段相声。

 

黄健翔同志在参加上述活动的时候未和台里、频道以及播音组内的任何负责人通报,严重违反了台内的相关规定。不仅如此,为了参加上述活动,黄健翔同志以自己有事为由,要求安排值班的编辑将自己负责的节目取消由他人代替,导致2006年10月28日(周六)及29日(周日)夜间原本应由黄健翔同志负责解说的两场2006-2007赛季德国足球甲级联赛的直播,也由段暄同志临时代替。

黄健翔同志在2006年世界杯期间犯下了严重错误,世界杯之后,在台里、频道和其他相关领导的批评、教育和帮助下做出了深刻检查。因此,本着惩前毖后、治病救人的方针,台里、频道和相关部门给予了黄健翔改正错误、在原来的岗位上继续工作的机会。但是,现在看来,当时黄健翔同志的检查虽然深刻,仍然只是停留在了书面上,并未在思想上引起足够的重视。在黄健翔同志的内心深处,对于自己职位和责任的定位仍然不够清晰,因此,黄健翔同志才会在近期屡犯不止、明知故犯。另外,自体育中心改制成立播音组以来,播音组为强化管理,制定了很多相关的条例和细则,并多次召开会议,讨论、贯彻和传达。黄健翔同志则多次以有事为由请假,所有组内召开的会议仅仅参加过一次。

鉴于上述情况,我们认为,黄健翔同志的种种行为是一种无组织、无纪律的表现,但是,黄健翔同志本人并没有认识到这一点,思想上还存在着潜在的不良情绪,随时有再次犯下更为严重错误的可能,这样发展下去,将为台里和频道带来不可预料的严重后果,同时也为组内强化制度、强化管理带来了很大的压力。黄健翔同志的行为给许多年轻人带来了负面的不良影响,不利于组内良好风气的形成,更不利于队伍的建设和对年轻人的正面引导。

经过台里和中心的多年培养,黄健翔同志在社会上已经具有了一定的知名度,他的一举一动将直接影响到频道声誉和中央电视台的对外形象。因此,更应该加强对于黄健翔同志的管理和教育和处理。

鉴于上述情况,我们提请相关领导按照台播音员、主持人管理办法,对黄健翔同志所犯错误进行严肃处理,以警本人并对整个队伍建设提供良好氛围。

以上是体育频道编辑部对于黄健翔同志近期行为的呈报和相关

处理意见。

妥否,请批示。

 

 

                                  体育频道XXX

                                 2006年10月30日

~~~~~~~~~~~~~~~~~~~~~~~~

近期准备做全国各个城市生活/工作/娱乐的工具条,收集每个城市的信息于一身, 方便各地网民使用,绝对绿色软件,不带任何流氓性质,感兴趣的敬请关注, ^_^

IE 秀服务

www.ieshow.net

 

2006年11月13日

方法论对软件开发而言意味着什么?我们如何看待软件开发中的方法论?方法论能够成为软件开发的救命稻草吗?在读过此文后,这些疑惑就会得到解答。

在第一篇文章中,我们来了解标题中的一些词的含义。

  • 方法学是什么?
  • 敏捷是什么?
  • 为什么讨论架构?

方法论

方法论的英文为Methodology,词典中的解释为"A series of related methods or techniques"我们可以把它定义为软件开发(针对软件开发)的一整套方法、过程、规则、实践、技术。关于方法论的出现的问题,我很赞同Alistair Cockburn的一句话,"方法论源于恐惧。"出于对项目的超期、成本失控等等因素的恐惧,项目经理们从以前的经验出发,制定出了一些控制、监测项目的方法、技巧。这就是方法论产生的原因。

Agile Software Development一书中,作者提到了方法论的十三个要素,基本能够函盖方法论的各个方面:

  • 角色(Roles
  • 个性(Personality
  • 技能(Skills
  • 团队(Teams
  • 技术(Techniques
  • 活动(Activities
  • 过程(Process
  • 工件(Work products
  • 里程碑(Milestones
  • 标准(Standards
  • 质量(Quality
  • 工具(Tools
  • 团队价值(Team Values

它们之间的关系可以用一幅图来表示:

1. 方法论的十三个要素

很多的方法论,都涉及了上面列举的十三要素中的部分要素,因此,我们可以把方法论看作是一个抽象的、无穷的超集,而现实中的方法论都是指超集的一个有限的子集而已。它们之间的关系就好像有理数和1到100之间的整数的关系一样。不论是XP,还是UI设计经验之类,都属于方法论的一个子集,只是这两个子集之间有大小的差别而已。我们还应该看到,讨论一个完备的方法论是没有意义的,因此这种方法论铁定不存在,就好像你视图穷举出所有的有理数一样荒唐。因此,我们关于一个通用的方法论的说法也是无意义的。好的方法论,比如说XP、水晶系列,它们都有一个适合的范围,因为它们了解一点,自己并不是一个无所不能的方法论。

在现实中,我们其实不断的在接触方法论。比如说,为了控制项目的进度,项目经理要求所有的开发人员每周递交一份详细的进度报告,这就是一种方法、一种技巧。如果把开发过程中的这些技巧系统的组织起来,就能够成为一种方法论。你可能会说,那一种方法论的产生也太容易了吧。不,这样产生的方法论并没有太大的实用价值,没有实用价值的方法论根本就没有存在的必要。因此,一个成功的方法论是要能够为多个的项目所接受,并且能够成功实现软件的交付的方法论。

我和我的同事在实践中做了一些试验,希望能够把一些好的方法论应用于开发团队。试验的结果很无奈,方法论实施的效果并不理想,一开始我们认为是方法本身的原因,到后来,我们发现事情并不是这么简单。在试验的过程中,开发人员一致认同方法论的优势所在,但是在实施过程中,鲜有坚持的下来的。在Agile Software Development中,我发现作者遇到了和我们一样的问题。

Alistair Cockburn在和大量的项目团队的访谈之后,写成了Agile Software Development一书。在访谈之前,他笃定自己将会发现高度精确的过程控制是成功的关键所在,结果他发现事实并非如此,他把他的发现归结为7条定律。而我在实际中的发现也包含在这七条定律中,总结起来就只有两点:沟通和反馈。

只要能够保证良好的沟通和即时的反馈,那么开发团队即使并没有采用先进的方法论,一样可以成功。相反,那些"高质量"的团队却往往由于缺乏这两个因素而导致失败(我们这里指的失败是用户拒绝使用最终的软件)。最有效,而成本也最低的沟通方法就是面对面(face to face)的沟通,而随着项目团队的变大,或是另外一些影响因素的加入(比如地理位置的隔绝),面对面的沟通越来越难实现,这导致沟通的的成本逐渐加大,质量也慢慢下降。但这并不是说非面对面的沟通不可,重要的是我们需要知道不同的沟通方式的成本和质量并不相同。XP方法尤为强调面对面的沟通,通过现场客户、站立会议、结对编程等方式来保证沟通的有效。在我的经验中,一个开发团队其实是需要多种沟通方式的结合的。完全的面对面的沟通对某些团队来说是很难实现的,那么问题的关键就在于你如何应用沟通的方式来达到你希望的效果。在前不久结束的欧莱雅创业计划大赛上,有一支团队特别引人注目,他们彼此间素未谋面,仅仅凭借Internet和电话完成了高效的合作。他们虽然没有使用面对面的沟通方式,但是仍然达成了既定的目标。软件开发也是一样的,面对面的沟通是非常有必要的,但其它的沟通方式也是需要的。

再看反馈,不论是控制进度,还是保证客户的满意度,这些活动都需要管理成本。软件开发中的管理成本的一个通性就是伴随有中间产出物(intermediate delivery)。比如说我们的需求规约、分析文档、设计文档、测试计划,这些都属于中间产出物。中间产出物的增加将会带来效率下降的问题,因为开发人员的时间都花在了完成中间产出物的工作上,花在给软件新功能上的时间就减少了。而中间产出物的主要目的是两个,一个是为了保证软件如客户所愿,例如需求规约;另一个是为了作为团队中的其他成员工作的输入,例如开发计划、测试计划等。因此,我们也可以针对这两点来商讨对策,一种是采用迭代的思想,提高软件发布的频率,以保证客户的需求被确实的满足,另一种就是缩小团队的沟通范围,保证成员能够从其他人那里得到新的思路,而不是撰写规范的内部文档(内部文档指那些仅为内部开发人员之间的沟通所需要的文档)。

因此,一个软件项目的成功和你采用的开发方法论并没有直接的关系。

重量
我们根据把拥有大量artifact(RUP官方翻译为工件,意思是软件开发过程中的中间产物,如需求规约、设计模型等)和复杂控制的软件开发方法称为重型(Heavy Weight)方法,相对的,我们称artifact较少的方法为轻型(Light Weight)方法。在传统的观念中,我们认为重型方法要比轻型安全许多。因为我们之所以想出重型方法,就是由于在中大型的项目中,项目经理往往远离代码,他无法有效的了解目前的工程的进度、质量、成本等因素。为了克服未知的恐惧感,项目经理制定了大量的中间管理方法,希望能够控制整个项目,最典型的莫过于要求开发人员频繁的递交各种表示项目目前状态的报告。

Planning XP一书中有一段讨论轻重型方法论的精辟论述,它把重型方法论归结为一种防御性的姿态(defensive posture),而把轻型方法论归结为一种渴望成功(Plan to win)的心态。如果你是采用了防御性姿态,那么你的工作就集中在防止和跟踪错误上,大量的工作流程的制定,是为了保证项目不犯错误,而不是项目成功。而这种方法也不可谓不好,但前提是如果整个团队能够满足前面所提到的两个条件的话,项目也肯定会成功,但是重型方法论的一个弊端就在于,大家都在防止错误,都在惧怕错误,因此人和人之间的关系是很微妙的,要达到充分的沟通也是很难的。最终,连对人的评价也变成是以避免错误的多寡作为考评的依据,而不是成就。我们在做试验的时候,一位项目经理开玩笑说,"方法论源自项目经理的恐惧,这没错。但最糟糕的是整个团队只有项目经理一个人恐惧,如果能够做到人人的恐惧,那大家也就没有什么好恐惧的了。"这句话提醒了我们,如果一个团队的精神就是力求成功,那么这支团队的心态就和其它的团队不同了,尤其是对待错误的心态上。根本就没有必要花费大量的精力来预防错误,错误犯了就犯了,即时改正就可以了。这其实就是渴望成功的心态。

方法论的艺术
管理,被称为科学和艺术的融合体,而管理的艺术性部分很大程度的体现为人的管理上。我说,方法学,一样是科学和艺术的融合体。这是有依据的,其实方法论和管理学是近亲关系,管理学中有一门分支是项目管理,而在软件组织中,项目管理是非常重要的,方法学就是一种针对软件开发的一种特定的项目管理(或是项目管理的一个子集)。

重型方法最大的一个问题就在于他不清楚或忽略了艺术这个层次,忽视了人的因素,把人做为一个计量单位,一种资源,一种线性元素。而人的要素在软件开发中是非常重要的,软件开发实际上是一种知识、智力的转移过程,最终形成的产品是一种知识产品,它的成本取决于开发者的知识价值,因此,人是最重要的因素。而人这个要素是很难衡量的,每个人都有不同的个性、想法、经验、经历,这么多复杂的因素加在一起,就导致了人的不可预见性。因此,我们强调管人的艺术。

最简单的例子是,在重型方法中,我们的基本假设是对人的不信任。项目经理要控制项目。但不信任就会产生很多的问题,比如士气不高,计划赶不上变化,创新能力低下,跳槽率升高等等。人都是希望被尊重的,技术人员更看重这一点,而很多公司也口口声声说自己多么多么以人为本,可是采用的却是以不信任人为前提的开发方法,言行不一。我们说敏捷方法的出发点是相互信任,做到这一点是很难的,但是一旦做到了,那这个团队就是非常具有竞争力的。因此,这就产生了一个问题,在没有做到完全的相互信任之前,我们到底相不相信他人呢,这就是我提到的艺术性的问题,什么时候你要相信人?什么时候你不相信人,这些都是需要权衡的问题,也都是表现你艺术性的问题。

1 背景
1.1 作者URL
http://spaces.msn.com/members/sharklee/?partqs=cat%3D%25e8%25ae%25a1%25e7%25ae%2597%25e6%259c%25ba%25e4%25b8%258e+Internet&_c11_blogpart_blogpart=blogview&_c=blogpart

2 gsoap文档翻译计划
2.1 gsoap文档翻译计划(序)
 
前一阵子需要在unix c平台下创建一个webservice应用。头痛之余,上网查询相关资料,偶然发现了gsoap开发包。于是乎立即下载试用了一下,效果很好。在它的帮助下,我很快完成了webservice应用的设计开发工作。

今天,心里突然升起一个念头:为何不把整个gsoap的帮助文档翻译一下呢?一来可以方便与其他同仁的交流;二来也可以更好的理解gsoap的原理与思想。只是此项工程工作浩繁,须怀有革命的大无畏精神尚可完成也。

如今唯先写一序,实则有督促之意耳。

2.2 gsoap文档翻译计划(1、介绍)
 
1.介绍
 gSOAP编译工具提供了一个SOAP/XML 关于C/C++ 语言的实现,从而让C/C++语言开发web服务或客户端程序的工作变得轻松了很多。绝大多数的C++web服务工具包提供一组API函数类库来处理特定的SOAP数据结构,这样就使得用户必须改变程序结构来适应相关的类库。与之相反,gSOAP利用编译器技术提供了一组透明化的SOAP API,并将与开发无关的SOAP实现细节相关的内容对用户隐藏起来。gSOAP的编译器能够自动的将用户定义的本地化的C或C++数据类型转变为符合XML语法的数据结构,反之亦然。这样,只用一组简单的API就将用户从SOAP细节实现工作中解脱了出来,可以专注与应用程序逻辑的实现工作了。gSOAP编译器可以集成C/C++和Fortran代码(通过一个Fortran到C的接口),嵌入式系统,其他SOAP程序提供的实时软件的资源和信息;可以跨越多个操作系统,语言环境以及在防火墙后的不同组织。
 gSOAP使编写web服务的工作最小化了。gSOAP编译器生成SOAP的代码来序列化或反序列化C/C++的数据结构。gSOAP包含一个WSDL生成器,用它来为你的web服务生成web服务的解释。gSOAP的解释器及导入器可以使用户不需要分析web服务的细节就可以实现一个客户端或服务端程序。
 下面是gSOAP的一些特点:
 ×gSOAP编译器可以根据用户定义的C和C++数据结构自动生成符合SOAP的实例化代码。
 ×gSOAP支持WSDL 1.1, SOAP 1.1, SOAP 1.2, SOAP RPC 编码方式以及 literal/document 方式.
 ×gSOAP是少数完全支持SOAP1.1 RPC编码功能的工具包,包括多维数组及动态类型。比如,一个包含一个基类参数的远程方法可以接收客户端传来的子类实例。子类实例通过动态绑定技术来保持一致性。
 ×gSOAP 支持 MIME (SwA) 和 DIME 附件包。
 ×gSOAP是唯一支持DIME附件传输的工具包。它允许你在保证XML可用性的同时能够以最快的方式(流方式)传递近乎无大小限制的二进制数据。
 ×gSOAP 支持 SOAP-over-UDP。
 ×gSOAP 支持 IPv4 and IPv6.
 ×gSOAP 支持 Zlib deflate and gzip compression (for HTTP, TCP/IP, and XML file storage)。
 ×gSOAP 支持 SSL (HTTPS)。
 ×gSOAP 支持 HTTP/1.0, HTTP/1.1 保持连接, 分块传输及基本验证。
 ×gSOAP 支持 SOAP 单向消息。
 ×gSOAP 包含一个 WSDL 生成器,便于web服务的发布。
 ×gSOAP 包含一个WSDL解析器 (将WSDL转换为gSOAP头文件),可以自动化用户客户端及服务端的开发。
 ×生成可以单独运行的web服务及客户端程序。
 ×因为只需要很少内存空间,所以可以运行在类似Palm OS, Symbian, Pocket PC的小型设备中。
 ×适用于以C或C++开发的web服务中。
 ×跨平台:Windows, Unix, Linux, Mac OS X, Pocket PC, Palm OS, Symbian等。
 ×支持序列化程序中的本地化C/C++数据结构。
 ×可以使用输入和输出缓冲区来提高效率,但是不用完全消息缓冲来确定HTTP消息的长度。取而代之的是一个三相序列化方法。这样,像64位编码的图像就可以在小内存设备(如PDA)中以DIME附件或其他方式传输。
 ×支持C++单继承,动态绑定,重载,指针结构(列表、树、图、循环图,定长数组,动态数组,枚举,64位2进制编码及16进制编码)。
 ×不需要重写现有的C/C++应用。但是,不能用unions,指针和空指针来作为远程方法调用参数的数据结构中元素。
 ×三相编组:1)分析指针,引用,循环数据结构;2)确定HTTP消息长度;3)将数据序列化位SOAP1.1编码方式或用户定义的数据编码方式。
 ×双相编组:1)SOAP解释及编码;2)分解“forward”指针(例如:分解SOAP中的href属性)。
 ×完整可定制的SOAP错误处理机制。
 ×可定制的SOAP消息头处理机制,可以用来保持状态信息

2.3 gsoap文档翻译计划(2、符号规定)
 
懒得翻译了,因为也不能再现出原来的版式。后面章节中分别注明吧,

2.4 gsoap文档翻译计划(3)
 
3. gSoap2.5版与gSOAP 2.4版(或以前版本)的不同
 按照WS-I Basic Profile 1.0a的要求,gSOAP2.5及以上版本默认使用SOAP RPC文字。这不需要去关心,因为WSDL解析器wsdl2h在你提供一个WSDL文档时,会自动注意这些不同点。增加了一个soapcpp2编译器的编译选项 -e ,用来保持与gSOAP2.4及以前版本的兼容性。

2.5 gsoap文档翻译计划(4)
 
4  gSoap2.2版与gSOAP 2.1版(或以前版本)的不同
 如果你是从2.1版升级到2.2或以后版本,请注意这些变化。
 为了能够分离传输、内容编码、映射中的接收/发送设置,改变了运行时选项及标志。这些标志分布再四个类中:传输(IO),内容编码(ENC),XML编组(XML)及C/C++数据映射。不再提倡使用旧标志soap_disable_X及soap_enable_X(其中,X表示选项名)。具体内容请参见9.12节。

2.6 gsoap文档翻译计划(5)
 
5. gSoap2.x版与gSOAP 1.x版的不同
 如果你是从1.x版升级到2.x版,请注意下面的内容。
 gSOAP2.0及之后的版本是在1.x版基础上重写的。gSOAP2.0之后的版本是线程安全的,但之前版本不是。gSOAP2.x版本中的主要文件已经重新命名,以便与1.x版区分。

gSOAP 1.X  gSOAP 2.X 
soapcpp  soapcpp2 
soapcpp.exe  soapcpp2.exe 
stdsoap.h  stdsoap2.h 
stdsoap.c  stdsoap2.c 
stdsoap.cpp  stdsoap2.cpp 
 
 从1.x版升级到2.x版并不需要进行大量的代码重写工作。所有2.x版相关的函数都定义在stdsoap2.c[pp]文件中,这个文件是由gSOAP编译器自动生成的。所以,用1.x版开发的服务端或客户端代码需要进行修改以适应2.x版中函数的变化:在2.x版中,所有的gSOAP函数都增加了一个参数用来保存一个gSOAP运行环境实例。这个参数包括了文件描述,表,缓冲,标志位等,它在所有gSOAP函数中都是第一个参数。
 gSOAP运行环境实例是一个struct soap类型的变量。当客户端程序访问远程方法前或当服务端程序能够接收一个请求前,必须先将这个运行环境变量初始化。在2.x版中新增了3个函数来负责这些事情:
 函数                        解释
 soap_init(struct soap *soap)         初始化环境变量(只需执行一次)
 struct soap *soap_new()            定义并初始化环境变量并返回一个该变量的指针
 struct soap *soap_copy(struct soap *soap)   定义一个环境变量并从已有的环境变量中拷贝环境信息
 
  环境变量定义好后就可以重复使用而不必再次初始化了。只有当线程独占访问时,我们才需要一个新的环境变量。例如,下面的代码分配了一个用于多个远程方法的环境变量:
 int main()
{
   struct soap soap;
   …
   soap_init(&soap); // 初始化环境变量
   …
   soap_call_ns__method1(&soap, …); // 调用一个远程方法
   …
   soap_call_ns__method2(&soap, …); // 调用另一个远程方法
   …
   soap_end(&soap); // 清除环境变量
   …
}
 我们也可以像下面这样定义环境变量:
 int main()
{
   struct soap *soap;
   …
   soap = soap_new(); // 定义并初始化环境变量
   if (!soap) // 如果不能定义,退出
   …
   soap_call_ns__method1(soap, …); // 调用远程函数
   …
   soap_call_ns__method2(soap, …); // 调用另一个远程函数
   …
   soap_end(soap); // 清除环境变量
   …
   free(soap); // 释放环境变量空间
}
 
 服务端代码在调用soap_serve函数前,需要定义相关环境变量:

int main()
{
   struct soap soap;
   soap_init(&soap);
   soap_serve(&soap);

 或者像下面这样:

int main()
{
   soap_serve(soap_new());

 soap_serve函数用来处理一个或多个(当允许HTTP keep-alive时,参见18.11节中的SOAP_IO_KEEPALIVE标志)请求。
 一个web服务可以用多线程技术来处理请求:
int main()
{
   struct soap soap1, soap2;
   pthread_t tid;
   …
   soap_init(&soap1);
   if (soap_bind(&soap1, host, port, backlog) < 0) exit(1);
   if (soap_accept(&soap1) < 0) exit(1);
   pthread_create(&tid, NULL, (void*(*)(void*))soap_serve, (void*)&soap1);
   …
   soap_init(&soap2);
   soap_call_ns__method(&soap2, …); // 调用远程方法
   …
   soap_end(&soap2);
   …
   pthread_join(tid, NULL); // 等待线程结束
   soap_end(&soap1); // 释放环境变量

 在上面的例子中,需要两个环境变量信息。而在1.x版本中,由于静态分配环境变量,多线程技术是不被允许的(只有一个线程可以用这个环境变量调用远程方法或处理请求信息)。
 8.2.4节将给出一个具体的多线程服务实例,它为每个SOAP请求分配一个独立线程进行处理。
2.7 gsoap文档翻译计划(6)
 
gSOAP 使用下面的软件包验证了其可用性: Apache 2.2 Apache Axis ASP.NET Cape Connect Delphi easySOAP++ eSOAP Frontier GLUE Iona XMLBus kSOAP MS SOAP Phalanx SIM SOAP::Lite SOAP4R Spray SQLData Wasp Adv. Wasp C++ White Mesa xSOAP ZSI 4S4C

2.8 gsoap文档翻译计划(7)
 
7  准备工作

 要开始用gSOAP创建一个web服务应用, 你需要:

 一个C/C++编译器.
 拥有根据操作系统平台创建的可执行的gSOAP的stdsoap2(windows下为stdsoap2.exe)编译器。
 拥有根据操作系统平台创建的可执行的gSOAP的wsdl2h(windows下为wsdl2h.exe)WSDL解析器。
 需要’stdsoap2.c’或’stdsoap2.cpp’及’stdsoap2.h’文件来实现你的SOAP功能。你可以创建一个dll或动态库以便简化连接。
 如果你要支持SSL(HTTPS)及压缩的话,可以安装OpenSSL及Zlib库。
 gSOAP是独立开发包,不需要任何第三方的软件支持(除非你要用到OpenSSL及Zlib)。
 与平台无关的gSOAP版本需要你下面的工具编译’soapcpp2′及’wsdl2h’文件:
 一个C++编译器(用来编译’wsdl2h’WSDL解析器)。
 Bison 或 Yacc
 Flex 或 Lex
 推荐使用Bison及Flex。
 在软件包samples目录下有大量的开发实例。可以用’make’来编译这些例子。这些例子包含了gSOAP中的各个方面。其中,最简单的例子是 one-liners(samples/oneliners)。

2.9 gsoap文档翻译计划(8.1.1)
 
8  快速指南
 本指南旨在让你快速开始你的gSOAP开发之旅。阅读本节的内容,需要你对SOAP 1.1协议及C/C++语法有大体的了解。虽然使用gSOAP编译器可以直接用C/C++开始编写web服务及客户端程序而不需要了解SOAP协议的细节,但是由于我们在本节中使用了大量的实例来说明gSOAP与其他SOAP实现的连接及通讯,所以了解一些SOAP及WSDL协议也是必需的。
 
8.1 如何使用gSOAP编译环境来编译SOAP客户端程序
 通常,一个SOAP客户端应用的实现需要为每个客户端需要调用的远程方法提供一个存根例程(stub routine)。存根例程主要负责编码参数信息;将包含参数信息的调用请求发送给制定的SOAP服务;等待返回结果;将结果中的参数信息编码。客户端程序调用访问远程方法的存根例程就像调用本地方法一样。用C/C++手工别写一个存根例程是个十分痛苦的差使,尤其当远程方法的参数中包含特定的数据结构(如:记录、数组、图等)时。幸运的是,gSOAP包中的’wsdl2h’WSDL解析器和’soapcpp2’存根及架构编译器能够将web服务客户端及服务端的开发工作自动化。
 ’soapcpp2’存根及架构编译器是可以生成构建C++ SOAP客户端所需的C++源码的预编译器。该预编译器的输入参数是一个标准的C/C++头文件。这个头文件可以由WSDL解析器根据相关的WSDL文档自动生成。
 参见下面的命令:
 $ wsdl2h -o quote.h http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl
 上面的命令根据制定URL提供的WSDL文档生成一个C++语法结构的头文件。
 如果需要生成一个纯C的头文件,需要一下命令:
 $ wsdl2h -c -o quote.h http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl
 更多关于WSDL解析器及其选项的细节信息,请参见8.2.10节。
 执行上述命令后,quote.h文件就生成了。其中包含开发客户端或服务端程序的存根例程定义。SOAP服务远程方法以函数声明的方式在这个头文件中被定义。C/C++源代码的存根例程将通过预编译器自动实现。同时,每个远程方法的程序框架也被自动生成了,它可以用来建立SOAP服务端程序应用。
 SOAP服务的输入输出参数可以是简单的数据类型或复杂的数据结构,可以由WSDL解析器自动生成或手工定义。预编译器将自动生成序列化/反序列化这些数据的代码,以便存根例程可以将这些数据以XML的方式编码或解码。

8.1.1  例子
 XMethods Delayed Stock Quote 服务提供一个getQuote方法(由’wsdl2h’WSDL解析器生成的quote.h定义)。这个方法根据提供的股票名称返回相应的股票价格。下面是这个方法的WSDL文档信息:

Endpoint URL:  http://services.xmethods.net:80/soap 
SOAP action:  "" (2 quotes) 
Remote method namespace:  urn:xmethods-delayed-quotes 
Remote method name:  getQuote 
   Input parameter:  symbol of type xsd:string 
   Output parameter:  Result of type xsd:float 
 
 下面是由WSDL解析器生成的getQuote.h头文件(实际的文件内容与’wsdl2h’版本及生成选项有关):
//gsoap ns1 service name: net_DOTxmethods_DOTservices_DOTstockquote_DOTStockQuoteBinding
//gsoap ns1 service type: net_DOTxmethods_DOTservices_DOTstockquote_DOTStockQuotePortType
//gsoap ns1 service port: http://66.28.98.121:9090/soap
//gsoap ns1 service namespace: urn:xmethods-delayed-quotes
//gsoap ns1 service documentation: Definitions generated by the gSOAP WSDL parser 1.0
// Service net.xmethods.services.stockquote.StockQuoteService : net.xmethods.services.stockquote.StockQuote web service

//gsoap ns1 service method-style: getQuote rpc
//gsoap ns1 service method-encoding: getQuote http://schemas.xmlsoap.org/soap/encoding/
//gsoap ns1 service method-action: getQuote urn:xmethods-delayed-quotes#getQuote
int ns1__getQuote(char *symbol, float &Result);

 这个头文件用C/C++代码为gSOAP预编译器指定了web服务的细节。远程方法被定义为函数ns1__getQuote,同时指定了客户端调用web服务所需的所有细节信息。
 getQuote远程方法需要一个名为symbol的字符串作为输入参数,同时需要一个名为Result的浮点数作为输出参数。预编译器生成的远程方法调用函数中,最后一个参数必须是输出参数,该参数以引用方式传递或定义为指针类型。除此之外的所有参数都是输入参数,这些参数必须以传值方式传递。函数返回一个整型值,其值说明web服务调用成功或出现的错误。具体的错误代码信息参见10.2节。
 函数名中命名空间前缀ns1__的细节信息将在8.1.2节中讨论。简单的说,命名空间前缀与函数名之间用两个下划线分割。比如,ns1__getQuote中,ns1为命名空间前缀,getQuote是函数名称。(函数名中单个下划线将在XML中解释为破折号-,因为在XML中破折号比下划线更常用,细节请参见10.3节)
 用下面命令执行预编译器:
 
soapcpp2 getQuote.h 

 预编译器根据getQuote.h中定义的信息来生成存根例程的代码框架。这个存根例程可以在客户端程序中随处调用。存根例程被声明为下面的样子:

int soap_call_ns1__getQuote(struct soap *soap, char *URL, char *action, char *symbol, float &Result); 

 存根例程保存在soapClient.cpp文件中;soapC.cpp文件包含了序列化、反序列化数据的函数。你可以用 -c编译选项来生成纯C的代码。
 注意,soap_call_ns1__getQuote在ns1__getQuote的参数基础上又增加了三个参数:soap必须是指向一个gSOAP运行环境的合法指针;URL是web服务的URL;action指明了web服务需要的SOAP action。XMethods Delayed Stock Quote服务的URL是http://66.28.98.121:9090/soap,action是"" (2 quotes)。你可以动态的改变URL及action。如果上述两个变量定义为NULL,则会使用头文件中定义的信息。
 下面的例子调用远程方法获取IBM的股票信息:

#include "soapH.h" // 包含生成的存根例程定义
#include "net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding.nsmap" // 包含命名空间表
int main()
{
   struct soap soap; // gSOAP运行环境
   float quote;
   soap_init(&soap); // 初始化运行环境(只执行一次)
   if (soap_call_ns1__getQuote(&soap, NULL, NULL, "IBM", &quote) == SOAP_OK)
      std::cout << "Current IBM Stock Quote = " << quote << std::endl;
   else // an error occurred
      soap_print_fault(&soap, stderr); // 在stderr中显示错误信息
   soap_destroy(&soap); // 删除类实例(仅用于C++中)
   soap_end(&soap); // 清除运行环境变量
   soap_done(&soap); // 卸载运行环境变量
   return 0;

 调用成功后,存根例程返回SOAP_OK同时quote变量保存着股票信息;如果调用失败则产生一个错误,同时通过soap_print_fault函数显示错误信息。
 gSOAP编译器同时为C++客户端程序生成了一个代理类。

#include "soapnet_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBindingProxy.h" // 获得代理
#include "net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding.nsmap" // 包含命名空间表
int main()
{
   net q; // "net" 是这个服务代理类的短名称
   float r;
   if (q.ns1__getQuote("IBM", r) == SOAP_OK)
      std::cout << r << std::endl;
   else
      soap_print_fault(q.soap, stderr);
   return 0;

 代理类的构造函数定义并初始化了一个gSOAP环境变量实例。所有的HTTP及SOAP/XML处理被隐藏在后台处理。你可以改变WSDL解析器生成的头文件中web服务的名称。web服务的名字是由WSDL内容中萃取的,并不总是短名称格式的。你可以随意更改这个条目

//gsoap ns1 service name: net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding 

来使用一个更合适的名字。这个名字将决定代理类文件及XML命名空间表文件的名字。
 下面的函数可以用来建立一个gSOAP运行环境(struct soap):
soap_init(struct soap *soap)  初始化运行环境变量(只需要执行一次)
soap_init1(struct soap *soap, soap_mode iomode)  初始化运行环境变量同时设置in/out模式
soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)  初始化运行环境变量同时分别设置in/out模式
struct soap *soap_new()  定义、初始化运行环境并返回一个执行运行环境的指针
struct soap *soap_new1(soap_mode iomode)  定义、初始化运行环境并返回一个执行运行环境的指针并设置in/out模式
struct soap *soap_new2(soap_mode imode, soap_mode omode)  定义、初始化运行环境并返回一个执行运行环境的指针并分别设置in/out模式
struct soap *soap_copy(struct soap *soap)  定义一个新的环境变量并将现有环境信息赋值给新的变量
soap_done(struct soap *soap)  重置、关闭连接,清除环境变量
 
 环境变量可以在程序中任意次数的使用。每个新的线程就需要一个新的环境变量实例。
 当例子中的客户端程序执行时,SOAP请求通过soap_call_ns1__getQuote函数来调用,它生成下面的SOAP RPC请求信息:
POST /soap HTTP/1.1
Host: services.xmethods.net
Content-Type: text/xml
Content-Length: 529
SOAPAction: ""

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:ns1="urn:xmethods-delayed-quotes"
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getQuote>
<symbol>IBM</symbol>
</ns1:getQuote>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope> 

 XMethods Delayed Stock Quote 服务返回如下的信息:
HTTP/1.1 200 OK
Date: Sat, 25 Aug 2001 19:28:59 GMT
Content-Type: text/xml
Server: Electric/1.0
Connection: Keep-Alive
Content-Length: 491

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
   soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/?
<soap:Body>
<n:getQuoteResponse xmlns:n="urn:xmethods-delayed-quotes?
<Result xsi:type="xsd:float?41.81</Result>
</n:getQuoteResponse>
</soap:Body>
</soap:Envelope>

 服务返回的信息通过存根例程来解析,并保存在soap_call_ns1__getQuote函数的quote参数中。
 客户端程序可以在任意时间多次调用远程方法。请看下面的例子:


struct soap soap;
float quotes[3]; char *myportfolio[] = {"IBM", "MSDN"};
soap_init(&soap); // need to initialize only once
for (int i = 0; i < 3; i++)
   if (soap_call_ns1__getQuote(&soap, "http://services.xmethods.net:80/soap", "", myportfolio[i], &quotes[i]) != SOAP_OK)
      break;
if (soap.error) // an error occurred
   soap_print_fault(&soap, stderr);
soap_end(&soap); // clean up all deserialized data
… 

 这个客户端程序通过调用ns1__getQuote存根例程来为数组中的每个股票代码获得信息。
 上面的例子给我们示范了使用gSOAP创建一个SOAP客户端时多么容易的事情啊。
2.10 gSoap文档翻译计划(8.1.2~8.1.3)
 
8.1.2 关于命名空间
 函数ns1__getQuote(上节提到的)中,使用了ns1__作为远程方法的命名空间。使用命名空间是为了防止远程方法名冲突,比方多个服务中使用同一个远程方法名的情况。
 命名空间前缀及命名空间名称同时也被用来验证SOAP信息的内容有效性。存根例程通过命名空间表中的信息来验证服务返回信息。命名空间表在运行时被取出用于解析命名空间绑定,反序列化数据结构,解码并验证服务返回信息。命名空间表不应该包含在gSOAP预编译器所需输入的头文件中。在18.2节中将会对命名空间表做详细介绍。
 Delayed Stock Quote服务客户端的命名空间表如下:

struct Namespace namespaces[] =
{   // {"命名前缀", "空间名称"}
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, // 必须是第一行
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, // 必须是第二行
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, // 必须是第三行
   {"xsd", "http://www.w3.org/2001/XMLSchema"}, // 2001 XML 大纲
   {"ns1", "urn:xmethods-delayed-quotes"}, // 通过服务描述获取
   {NULL, NULL} // 结束
};

 第一行命名空间是SOAP1.1协议默认命名空间。事实上,命名空间表就是用来让程序员可以规定SOAP编码方式,能够用包含命名空间的命名空间前缀来满足指定SOAP服务的命名空间需求的。举例来说,使用前面命名空间表中定义的命名空间前缀ns1,存根例程就可以对getQuote方法的请求进行编码。这个过程由gSOAP预编译器通过在getQuote.h文件中定义的包含前缀ns1的ns1__getQuote函数自动完成。通常,如果要在远程方法名,结构名,类名,字段名等结构或类中使用命名空间前缀,就必须在命名空间表中进行定义。
 命名空间表将会被存根例程封装,并按下面的形式输出:


<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:ns1="urn:xmethods-delayed-quotes"
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
… 

 这个命名空间绑定将被SOAP服务用来验证SOAP请求。

8.1.3 例子
 使用命名空间前缀可以解决在不同的服务中使用相同名称的远程方法的问题,看下面的例子:

// Contents of file "getQuote.h":
int ns1__getQuote(char *symbol, float &Result);
int ns2__getQuote(char *ticker, char *&quote); 

 这个例子允许客户端程序使用不同的命名空间以便连接到不同的服务程序执行其中的远程方法。
 命名空间前缀也可以用在类声明中使用,在XML大纲中区分同名但不同命名空间的SOAP值。例如:

class e__Address // an electronic address
{
   char *email;
   char *url;
};
class s__Address // a street address
{
   char *street;
   int number;
   char *city;
}; 

 在生成的序列化函数中,使用e__Address的一个实例来表示e命名空间前缀的一个地址元素类型。

<e:Address xsi:type="e:Address">
<email xsi:type="string">me@home</email>
<url xsi:type="string">www.me.com</url>
</e:Address> 

 用s__Address的一个实例来表示s命名空间前缀的一个地址元素类型。

<s:Address xsi:type="s:Address">
<street xsi:type="string">Technology Drive</street>
<number xsi:type="int">5</number>
<city xsi:type="string">Softcity</city>
</s:Address> 

 客户端程序的命名空间表必须有e和s的数据类型定义:

struct Namespace namespaces[] =
{ …
   {"e", "http://www.me.com/schemas/electronic-address"},
   {"s", "http://www.me.com/schemas/street-address"},
… 

 命名空间表必须作为客户端程序的一部分,使客户端程序在运行时可以对数据进行序列化及反序列化。
2.11 gsoap翻译计划(8.1.4~8.1.6)
 
8.1.4 如何建立客户端程序代理类
 用于C++客户端程序的代理类信息是由gSOAP预编译器自动创建的。为了说明代理类的生成过程,我们在getQuote.h头文件中加入一些信息,以便gSOAP预编译器可以生成代理类。这些信息就类似于WSDL解析器自动生成的头文件中就已经包含的信息。

//"getQuote.h"的内容:
//gsoap ns1 service name: Quote
//gsoap ns1 service location: http://services.xmethods.net/soap
//gsoap ns1 service namespace: urn:xmethods-delayed-quotes
//gsoap ns1 service style: rpc
//gsoap ns1 service encoding: encoded
//gsoap ns1 service method-action: getQuote ""
int ns1__getQuote(char *symbol, float &Result); 

 前三行指令用于定义代理类的名称,服务地址,命名空间。第四行、第五行指令定义了使用SOAP RPC编码方式。最后一行定义了可选的SOAPAction。当需要SOAPAction时,这行信息将提供给每个远程方法。使用soapcpp2对该头文件进行编译后,将会产生soapQuoteProxy.h文件。它包含下面的内容:

#include "soapH.h"
class Quote
{ public:
   struct soap *soap;
   const char *endpoint;
   Quote() { soap = soap_new(); endpoint = "http://services.xmethods.net/soap"; };
   ~Quote() { if (soap) { soap_destroy(soap); soap_end(soap); soap_done(soap); free((void*)soap); }};
   int getQuote(char *symbol, float &Result) { return soap ? soap_call_ns1__getQuote(soap, endpoint, "", symbol, Result) : SOAP_EOM; };
}; 

 为了能够在运行时刻对gSOAP环境变量及命名空间进行定制,上述两个变量被定义程全局变量。
 生成的代理类可以同命名空间表一起包含在客户端程序中,请看下面的例子:

#include "soapQuoteProxy.h" // 获得代理类
#include "Quote.nsmap" // 获得命名空间绑定
int main()
{
   Quote q;
   float r;
   if (q.ns1__getQuote("IBM", r) == SOAP_OK)
      std::cout << r << std::endl;
   else
      soap_print_fault(q.soap, stderr);
   return 0;

 Quote构造函数定义并初始化了一个gSOAP运行环境实例。所有的HTTP及SOAP/XML进程都被隐藏在后台自动执行。
 如果你需要多个命名空间表或要联合多个客户端,你可以在执行soapcpp2时添加参数-n及-p来生成命名空间表以防止冲突。详细信息请看9.1及18.33节。同时,你可以使用C++代码命名空间来创建一个命名空间限制的代理类,详细信息请看18.32节。

8.1.5  XSD 类型编码
 许多SOAP服务需要在SOAP负载中使用XML编码。在gSOAP预编译器中使用的默认编码为SOAP RPC编码。然而,使用XSD类型编码可以改善互操作性。XSD类型在头文件中用typedef定义。举个例子,下面的定义将C/C++类型转换为XSD类型:

// Contents of header file:

typedef char *xsd__string; // encode xsd__string value as the xsd:string schema type
typedef char *xsd__anyURI; // encode xsd__anyURI value as the xsd:anyURI schema type
typedef float xsd__float; // encode xsd__float value as the xsd:float schema type
typedef long xsd__int; // encode xsd__int value as the xsd:int schema type
typedef bool xsd__boolean; // encode xsd__boolean value as the xsd:boolean schema type
typedef unsigned long long xsd__positiveInteger; // encode xsd__positiveInteger value as the xsd:positiveInteger schema type
… 

 这些简单的声明告诉gSOAP预编译器当远程方法参数中使用上述定义的类型时,就把相关的C++类型转当作内建的XSD类型进行编码、解码。同时,使用typedef不需要使用内建C++类型的客户端或服务端程序更改现有代码(但只是当参数为简单的C++类型时,请参看11.2.2节来使用XSD类型表示组合的数据类型)。

8.1.6 例子
 
 重新考虑一席getQuote的例子。现在用XSD类型来重写代码:

// Contents of file "getQuote.h":
typedef char *xsd__string;
typedef float xsd__float;
int ns1__getQuote(xsd__string symbol, xsd__float &Result); 

 使用预编译器编译这个头文件,将会生成与原来相同的存根例程代码:

int soap_call_ns1__getQuote(struct soap *soap, char *URL, char *action, char *symbol, float &Result); 

 客户端程序不需要进行任何改动,即可使用XSD类型类编码、解码数据类型信息了。
 举个例子,当客户端程序调用代理时,代理方法用xsd:string类型产生一个SOAP请求:


<SOAP-ENV:Body>
<ns1:getQuote><symbol xsi:type="xsd:string">IBM</symbol>
</ns1:getQuote>
</SOAP-ENV:Body>
… 

服务端的返回码为:


<soap:Body>
<n:getQuoteResponse xmlns:n="urn:xmethods-delayed-quotes">
<Result xsi:type="xsd:float">41.81</Result>
</n:getQuoteResponse>
</soap:Body>
… 

 

 
Rundll32.exe是什么?顾名思意,“执行32位的DLL文件”。它的作用是执行DLL文件中的内部函数,这样在进程当中,只会有Rundll32.exe,而不会有DLL后门的进程,这样,就实现了进程上的隐藏。如果看到系统中有多个Rundll32.exe,不必惊慌,这证明用Rundll32.exe启动了多少个的DLL文件。当然,这些Rundll32.exe执行的DLL文件是什么,我们都可以从系统自动加载的地方找到。

现在,我来介绍一下Rundll32.exe这个文件,意思上边已经说过,功能就是以命令行的方式调用动态链接程序库。系统中还有一个Rundll.exe文件,他的意思是“执行16位的DLL文件”,这里要注意一下。在来看看Rundll32.exe使用的函数原型:
Void CALLBACK FunctionName (
HWND hwnd,
HINSTANCE hinst,
LPTSTR lpCmdLine,
Int nCmdShow
);

其命令行下的使用方法为:Rundll32.exe DLLname,Functionname [Arguments]
DLLname为需要执行的DLL文件名;Functionname为前边需要执行的DLL文件的具体引出函数;[Arguments]为引出函数的具体参数。

略谈Rundll32.exe的作用

常用Windows9x的朋友一定对Rundll32.exe和Rundll.exe这两个档案不会陌生吧,不过,由於这两个程式的功能原先只限於在微软内部使用,因而真正知道如何使用它们的朋友想必不多。那么好,如果你还不清楚的话,那么就让我来告诉你吧。

首先,请你做个小实验(请事先保存好你正在执行的程式的结果,否则…):点击“开始-程式-Ms-Dos方式”,进入Dos视窗,然後键入rundll32.exe user.exe,restartwindows,再按下回车键,这时你将看到,机器被重启了!怎么样,是不是很有趣?

当然,Rundll的功能绝不仅仅是重启你的机器。其实,Rundll者,顾名思义,执行Dll也,它的功能就是以命令列的方式呼叫Windows的动态链结库,Rundll32.exe与Rundll.exe的区别就在於前者是呼叫32位的链结库,而後者是运用於16位的链结库,它们的命令格式是: RUNDLL.EXE ,,

这里要注意三点:1.Dll档案名中不能含有空格,比如该档案位於c:\ProgramFiles\目录,你要把这个路径改成c:\Progra~1\;2.Dll档案名与Dll入口点间的逗号不能少,否则程式将出错并且不会给出任何资讯!3.这是最重要的一点:Rundll不能用来呼叫含返回值参数的Dll,例如Win32API中的GetUserName(),GetTextFace()等。在Visual Basic中,提供了一条执行外部程式的指令Shell,格式为:Shell “命令列”

如果能配合Rundll32.exe用好Shell指令,会使您的VB程式拥有用其他方法难以甚至无法实现的效果:仍以重启为例,传统的方法需要你在VB工程中先建立一个模组,然後写入WinAPI的声明,最後才能在程式中呼叫。而现在只需一句: Shell “rundll32.exe user.exe,restartwindows”就搞定了!是不是方便多了?

实际上,Rundll32.exe在呼叫各种Windows控制面板和系统选项方面有著独特的优势。下面,我就将本人在因特网上收集的有关Rundll的指令列举如下(很有用的,能省去你很多呼叫Windows API的时间!!),供大家在程式设计中引用:
命令列: rundll32.exe shell32.dll,Control_RunDLL
功能: 显示控制面板
命令列: rundll32.exe shell32.dll,Control_RunDLL access.cpl,,1
功能: 显示“控制面板-辅助选项-键盘”选项视窗
命令列: rundll32.exe shell32.dll,Control_RunDLL access.cpl,,2
功能: 显示“控制面板-辅助选项-声音”选项视窗
命令列: rundll32.exe shell32.dll,Control_RunDLL access.cpl,,3
功能: 显示“控制面板-辅助选项-显示”选项视窗
命令列: rundll32.exe shell32.dll,Control_RunDLL access.cpl,,4
功能: 显示“控制面板-辅助选项-滑鼠”选项视窗
命令列: rundll32.exe shell32.dll,Control_RunDLL access.cpl,,5
功能: 显示“控制面板-辅助选项-传统”选项视窗
命令列: rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl @1
功能: 执行“控制面板-添加新硬体”向导。
命令列: rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL AddPrinter
功能: 执行“控制面板-添加新印表机”向导。
命令列: rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,1
功能: 显示 “控制面板-添加/删除程式-安装/卸载” 面板。
命令列: rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,2
功能: 显示 “控制面板-添加/删除程式-安装Windows” 面板。
命令列: rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,3
功能: 显示 “控制面板-添加/删除程式-启动盘” 面板。
命令列: rundll32.exe syncui.dll,Briefcase_Create
功能: 在桌面上建立一个新的“我的公文包”。
命令列: rundll32.exe diskcopy.dll,DiskCopyRunDll
功能: 显示复制软碟视窗
命令列: rundll32.exe apwiz.cpl,NewLinkHere %1
功能: 显示“建立快捷方式”的对话框,所建立的快捷方式的位置由%1参数决定。
命令列: rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,0
功能: 显示“日期与时间”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,1
功能: 显示“时区”选项视窗。
命令列: rundll32.exe rnaui.dll,RnaDial [某个拨号连接的名称]
功能: 显示某个拨号连接的拨号视窗。如果已经拨号连接,则显示目前的连接状态的视窗。
命令列: rundll32.exe rnaui.dll,RnaWizard
功能: 显示“新建拨号连接”向导的视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0
功能: 显示“显示属性-背景”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,1
功能: 显示“显示属性-萤屏保护”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2
功能: 显示“显示属性-外观”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3
功能: 显示显示“显示属性-属性”选项视窗。
命令列: rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL FontsFolder
功能: 显示Windows的“字体”档案夹。
命令列: rundll32.exe shell32.dll,Control_RunDLL main.cpl @3
功能: 同样是显示Windows的“字体”档案夹。
命令列: rundll32.exe shell32.dll,SHformatDrive
功能: 显示格式化软碟对话框。
命令列: rundll32.exe shell32.dll,Control_RunDLL joy.cpl,,0
功能: 显示“控制面板-游戏控制器-一般”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL joy.cpl,,1
功能: 显示“控制面板-游戏控制器-进阶”选项视窗。
命令列: rundll32.exe mshtml.dll,PrintHTML (HTML文档)
功能: 列印HTML文档。
命令列: rundll32.exe shell32.dll,Control_RunDLL mlcfg32.cpl
功能: 显示Microsoft Exchange一般选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL main.cpl @0
功能: 显示“控制面板-滑鼠” 选项 。
命令列: rundll32.exe shell32.dll,Control_RunDLL main.cpl @1
功能: 显示 “控制面板-键盘属性-速度”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL main.cpl @1,,1
功能: 显示 “控制面板-键盘属性-语言”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL main.cpl @2
功能: 显示Windows“印表机”档案夹。
命令列: rundll32.exe shell32.dll,Control_RunDLL main.cpl @3
功能: 显示Windows“字体”档案夹。
命令列: rundll32.exe shell32.dll,Control_RunDLL main.cpl @4
功能: 显示“控制面板-输入法属性-输入法”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL modem.cpl,,add
功能: 执行“添加新调制解调器”向导。
命令列: rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,0
功能: 显示“控制面板-多媒体属性-音频”属性页。
命令列: rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,1
功能: 显示“控制面板-多媒体属性-视频”属性页。
命令列: rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,2
功能: 显示“控制面板-多媒体属性-MIDI”属性页。
命令列: rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,3
功能: 显示“控制面板-多媒体属性-CD音乐”属性页。
命令列: rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,4
功能: 显示“控制面板-多媒体属性-设备”属性页。
命令列: rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl @1
功能: 显示“控制面板-声音”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL netcpl.cpl
功能: 显示“控制面板-网路”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL odbccp32.cpl
功能: 显示ODBC32资料管理选项视窗。
命令列: rundll32.exe shell32.dll,OpenAs_RunDLL {drive:\path\filename}

功能: 显示指定档案(drive:\path\filename)的“打开方式”对话框。
命令列: rundll32.exe shell32.dll,Control_RunDLL password.cpl
功能: 显示“控制面板-密码”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL powercfg.cpl
功能: 显示“控制面板-电源管理属性”选项视窗。
命令列: rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL PrintersFolder
功能: 显示Windows“印表机”档案夹。(同rundll32.exe shell32.dll,Control_RunDLL main.cpl @2)
命令列: rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,0
功能: 显示“控制面板-区域设置属性-区域设置”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,1
功能: 显示“控制面板-区域设置属性-数字”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,2
功能: 显示“控制面板-区域设置属性-货币”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,3
功能: 显示“控制面板-区域设置属性-时间”选项视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,4
功能: 显示“控制面板-区域设置属性-日期”选项视窗。
命令列: rundll32.exe desk.cpl,InstallScreenSaver [萤屏保护档案名]
功能: 将指定的萤屏保护档案设置为Windows的屏保,并显示萤屏保护属性视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,0
功能: 显示“控制面板-系统属性-传统”属性视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,1
功能: 显示“控制面板-系统属性-设备管理器”属性视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,2
功能: 显示“控制面板-系统属性-硬体配置档案”属性视窗。
命令列: rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,3
功能: 显示“控制面板-系统属性-性能”属性视窗。
命令列: rundll32.exe user.exe,restartwindows
功能: 强行关闭所有程式并重启机器。
命令列: rundll32.exe user.exe,exitwindows
功能: 强行关闭所有程式并关机。
命令列: rundll32.exe shell32.dll,Control_RunDLL telephon.cpl
功能: 显示“拨号属性”选项视窗
命令列: rundll32.exe shell32.dll,Control_RunDLL themes.cpl
功能: 显示“桌面主旨”选项面板
当然,不止是VisualBasic,象Delphi.VisualC++等其他程式设计语言也可以通过呼叫外部命令的方法来使用Rundll的这些功能,具体方法这里就不再详细叙述了。灵活的使用Rundll,一定会使你的程式设计轻轻松松,达到事半功倍的效果!

 

2006年11月11日

IE秀网站www.ieshow.net 免费提供了在线制作工具条,用户可以Diy自己制作自己想要的工具条,功能极其强大,真是随心所欲阿,痛快了得!

我自己做了一个用来方便上网的迷你好123工具条,呵呵,说白了就是收藏夹功能,附带了其他一些系统功能,现在上网方便多了。

还具有IE的收藏功能,可以方便的导出/导入,呵呵,牛吧!

下载地址:

http://www.ieshow.net/toolbar/online/toolbar/toolbar_info.aspx?programeName=ProSiteAll