gsoap 的webservice和rss应用研究


简介:
    gsoap是一个webservice的toolkit,能依据wsdl文件生成server和client代码,产生的代码小巧简洁不依赖其他xml解析库,很容易移植,大大减轻webservice程序员的工作量。也就是说,gsoap是一个很好的代码生成工具。我下载了gsoap的源码,编译安装后做了一些测试,包括一个自己写的webservice和一个rss阅读器。
1.用tomcat和jbuilder生成一个webservice,引出两个方法:
  String sayhello() //返回"hello world"
  int sayit()  //返回1234
2.生成webservice调用接口文件
wsdl2h -c -o hello.h
http://10.3.37.116:8080/web1/services/hello?wsdl
说明:
    -c 产生纯C代码
    -o 生成的目标文件
    url webservice的wsdl文件
3.生成Client端调用代码文件
soapcpp2 -c hello.h
说明:产生以下文件
helloSoapBinding.nsmap   //xml的name space
helloSoapBinding.sayhello.req.xml  //sayhello方法请求内容
helloSoapBinding.sayhello.res.xml  //sayhello方法响应内容
helloSoapBinding.sayit.req.xml  //同上
helloSoapBinding.sayit.res.xml
soapC.c     //soap底层接口实现
soapClient.c     //soap client端接口实现
soapClientLib.c    //soap client端接口实现
soapH.h
soapServer.c    //soap server端接口实现
soapServerLib.c   //soap server端接口实现
soapStub.h   
4.编写测试代码
#include "soapH.h" /* include generated proxy and SOAP support */
int main(int argc, char **argv)
{ struct soap soap;
char buf[512];
struct ns1__sayhelloResponse q;
q.sayhelloReturn=buf;

  soap_init(&soap);
  //测试webservice提供的 sayhello 方法
  if (soap_call_ns1__sayhello(&soap, "
http://10.3.37.116:8080/web1/services/hello
", NULL, &q) == 0)
    printf("\nit say: %s \n",q.sayhelloReturn);
  else
    soap_print_fault(&soap, stderr);
  return 0;
}
SOAP_NMAC struct Namespace namespaces[] =
{
{"SOAP-ENV", "
http://schemas.xmlsoap.org/soap/envelope/
", "
http://www.w3.org/*/soap-envelope
", NULL},
{"SOAP-ENC", "
http://schemas.xmlsoap.org/soap/encoding/
", "
http://www.w3.org/*/soap-encoding
", NULL},
{"xsi", "
http://www.w3.org/2001/XMLSchema-instance
", "
http://www.w3.org/*/XMLSchema-instance
", NULL},
{"xsd", "
http://www.w3.org/2001/XMLSchema
", "
http://www.w3.org/*/XMLSchema
", NULL},
{"ns1", "
http://ws1
", NULL, NULL},
{NULL, NULL, NULL, NULL}
};
5.编译产生最终代码
cc -o hello hello.c soapC.c soapClient.c stdsoap2.c
说明:
    stdsoap2.c不是产生的,是gsoap的soap协议栈的一部分
    hello.c是我自己写的程序,调用服务器的sayhello方法
    soapC.c和soapClient.c是client端必须要用的代码。
6.rss阅读器,测试如下:
  soapcpp2 -c rss.h
  cc -o rss rss.c soapC.c stdsoap2.c charutil.c
说明:
  charutil.c 是我写的转码工具,xml一般只支持utf8编码,需要转成gbk编译才能正常显示
用法(以显示20条为例): rss 20
http://10.3.37.116:8080/now.xml

7.生成MIPS平台文件:
将CC换成mipsel-linux-gcc即可,一步通过,编译中没有发现问题。
8.rss代码分析
简洁
    RSS——全称Really Simple Syndication,中文译名叫简易信息聚合。它是一种网络协议,用来约定站点之间共享内容的简易方式(聚合内容),通常被用于新闻或Blog等网站.它的项目可能包含新闻的全部介绍,或者仅仅是摘要,最重要的是通常都能通过这些项目的链接到全部的内容.网络用户可以在不打开网站内容页面的情况下,阅读支持RSS输出的网站内容.
8.1.数据结构(在rss.h中定义,参考rss 2.0规范):
struct channel
{ char *title;
  char *link;
  char *language;
  char *copyright;
  XML description; // description may contain XHTML that we want to preserve
  struct image *image;
  int __size;
  struct item *item;
  time_t *dc__date; // RSS 2.0 dc schema element
};
struct item
{ char *title;
  char *link;
  XML description; // description may contain XHTML that we want to preserve
  char *pubDate;
  time_t *dc__date; // RSS 2.0 dc schema element
};
struct image
{ char *title;
  char *url;
  char *link;
  int width  0:1 = 0; // optional, default value = 0
  int height 0:1 = 0; // optional, default value = 0
  XML description; // description may contain XHTML that we want to preserve
};
struct rss
{ @char *version = "2.0";
  struct channel channel;
};
8.2.主要流程
连接RSS服务器 soap_connect_command(soap, SOAP_GET, endpoint, NULL)
接收信息  soap_begin_recv(soap)
解析RSS  rss = soap_get_rss(soap, NULL, "rss", NULL);
断开服务器 soap_end_recv(soap); soap_closesock(soap);
显示channel信息 rss->channel title,link,language,image等
循环显示新闻信息 rss->channel.item title,pubDate,description...
9.附录:RSS 2.0中文规范(转)
在一个RSS文档的开头是一个节点和一个规定的属性version,该属性规定了该文档将以RSS的哪个版本表示。
在节点的下一级是一个独立的节点,该节点包含关于channel的信息和内容。至少包括3项:
 title 频道(channel)名称。它可以告诉别人如何访问你的服务。如果你有一个与你的RSS文件内容一致的HTML网站,你的title元素值应该与你的网站的标题相同。
 link 响应该频道的网站的URL
 description 关于该频道的描述
channel的可选元素
下面是可选的频道元素列表
元素                  描述              范例  
language 使用的语言。这允许聚合器对所有的意大利语站点分组。 en-us
copyright 版权声明 Copyright 2002, Spartanburg Herald-Journal
managingEditor 内容负责人的Email
geo@herald.com
(George Matesky)
webMaster 技术人员的Email
betty@herald.com
(Betty Guernsey)
pubDate 内容的发布时间 Sat, 07 Sep 2002 00:00:01 GMT
lastBuildDate 最后更新时间 Sat, 07 Sep 2002 09:42:31 GMT
category 指定该频道所属的一个或多个分类。遵循与item级category元素相同的规则。 Newspapers
generator 生成该频道的程序名称 MightyInHouse Content System v2.3
docs 指向rss格式文档的url地址?
http://blogs.law.harvard.edu/tech/rss

cloud 允许所有进程注册一个cloud用于获得频道的更新通知,并为rss种子实现一个轻量级的发布订阅协议。  
ttl ttl是Time to live的缩写。它指示cache的有效保存时间。 60
image 与频道一起显示的图片地址
rating 该频道的统计图片地址
textInput 指定一个textbox与该频道一起显示
skipHours 告诉使用者哪些时段是可以忽略的
skipDays 告诉使用着哪些天是可以忽略的
子节点
是一个可选的子节点,该节点包含三个必需的子元素和三个可选的子元素。
是GIF、JPEG或PNG图像文件的URL地址,该图像代表整个频道
用于描述上面的图像,等同于HTML语言中的的alt属性
是要连接的站点的url,当显示频道时,图像的连接指向该站点。
和应该与频道的和有相同的值
可选的节点包括和,它们是数字类型,指定图像的宽度和高度,单位为像素
就是link的TITLE属性中文本,它将在调用网页时显示出来。
图像宽度的最大值为144,默认值为88
图像高度的最大值为400,默认值为31
子节点
是一个可选的子节点。
它指定一个可以支持rssCloud接口的web服务,rssCloud接口可以用HTTP-POST,XML-RPC或SOAP1.1实现。
它的目的是允许通知注册为cloud的进程频道被更新,从而实现一个轻量级的发布订阅协议。
在这个例子中,为了请求频道通知,你需要发送一个XML-RPC消息到rpc.sys.com的80端口,路径为/RPC2。调用的过程为myCloud.rssPleaseNotify。
子节点
是一个可选的子节点。
ttl是time to live的缩写。它表示频道在被刷新前应该被缓存的时间。这使得rss源可以被一个支持文件共享的网络所管理,例如Gnutella
例如:60
子节点
是的可选的子节点,包含四个子节点。
--提交按钮的标签
--该文本输入区的描述
--文本输入区的名称
--处理文本输入的CGI脚本的URL
使用的目的有些神秘(?)。你可以用它提供一个搜索引擎输入框,或让读者提供反馈信息。许多聚合器忽略该节点。
的节点
一个频道可以包含许多项目(item)节点。一个项目可以代表一个故事——比如说一份报纸或杂志上的故事,如果是这样的话,那么项目的描述则是故事的概要,项目的链接则指向整个故事的存放位置。项目的所有节点都是可选的,但是至少要包含至少一个标题(title)和描述(description)。
元素                  描述              范例
title item的标题 Venice Film Festival Tries to Quit Sinking
link item的URL
http://www.nytimes.com/2002/09/07/movies/07FEST.html

description item概要 Some of the most heated chatter at the Venice Film Festival this week was about the way that the arrival of the stars at the Palazzo del Cinema was being staged.
author 作者的email地址
oprah@oxygen.net

category item可以包含在一个或多个分类中 Simpsons Characters
comments 与item相关的评论的地址
http://www.myblog.org/cgi-local/mt
... gi?entry_id=290
enclosure 附加的媒体对象
guid 可以唯一确定item的字符串
http://inessential.com/2002/09/01.php#a2

pubDate item发布的时间 Sun, 19 May 2002 15:21:36 GMT
source rss频道来源 Quotes of the Day
子节点
是的可选节点。
它的值是item来自的rss频道的名称,从item的title衍生而来。它有一个必须包含的属性url, 该属性链接到XML序列化源。
该节点的作用是提高连接的声望,进一步推广新闻项目的源头。它可以用在聚合器的Post命令中。当从聚合器通过webblog访问一个item时,能够自动被生成。
子节点
是的可选节点。
它有三个必要的属性。url属性指示enclosure的位置,length指出它的字节大小,type属性指出它的标准MIME类型
url必须为一个http url。

子节点
是的可选节点。
它有一个可选属性或域,该属性是一个用来定义分类法的字符串。
该节点的值是一个正斜杠分割的字符串,它用来在指定的分类法中识别一个分级位置(hierarchic location)。处理器可以为分类的识别建立会话。(Processors may establish conventions for the interpretation of categories)下面有两个例子:
Grateful Dead
MSFTMSFT 你可以根据你的需要为不同的域(domain)包含很多category节点,并且可以在相同域的不同部分拥有一个前后参照的item。
子节点
是的可选节点。
它的值是item发布的日期。如果它是一个没有到达的日期,聚合器在日期到达之前可以选择不显示该item。
Sun, 19 May 2002 15:21:36 GMT
子节点
是的可选节点。
guid是globally unique identifier的缩写。它是一个可以唯一识别item的字符串。当item发布之后,聚合器可以选择使用该字符串判断该item是否是新的。
http://some.server.com/weblogItem3207
guid没有特定的语法规则,聚合器必须将他们看作一个字符串。生成具有唯一性的字符串guid取决于种子的源头。
如果guid节点有isPermaLink属性,并且值为真,读取器就会认为它是item的permalink。permalink是一个可在web浏览器中打开的url链接,它指向节点所描述的全部item。
http://inessential.com/2002/09/01.php#a2
isPermaLink是可选属性,默认值为真。如果值为假,guid将不会被认为是一个url或指向任何对象的url。
子节点
是的可选节点。
如果出现,它指向该item评论的url
http://rateyourmusic.com/yaccs/commentsn/blogId= ... Id=271
子节点
是的可选节点。
它是item的作者的email。对于通过rss传播的报纸和杂志,作者可能是写该item所描述的文章的人。对于聚集型webblogs,作者可能不是责任编辑或站长。对于个人维护的webblog,忽略节点是有意义的。