狂奔 lion

自强不息

浅谈Java中的通信机制及与C/C++ API的集成(下)

接着上次的话题,今天我们聊聊gSOAP这个框架,我们把用C写的旧有系统用gSOAP改造一下,通过SOA的形式发布出去。
上文提到,利用gSOAP可以做到以下3点:
1 一个Stand-alone的服务器外壳
2 一个根据API程序自动生成的Web Services服务
3 一个WSDL描述符文件

客户根据 WSDL 描述文档,会生成一个 SOAP 请求消息。Web Services 都是放在Web服务器后面,客户生成的SOAP请求会被嵌入在一个HTTP POST请求中,发送到 Web 服务器来。Web 服务器再把这些请求转发给 Web Services 请求处理器。请求处理器的作用在于,解析收到的 SOAP 请求,调用 Web Services,然后再生成相应的 SOAP 应答。Web 服务器得到 SOAP 应答后,会再通过 HTTP应答的方式把信息送回到客户端。
WSDL是Web服务中客户端和服务端沟通的桥梁,描述了对象提供的方法。SOAP帮我们制定了一份被官方认可的对象的封装方法。有了WSDL,客户端只关心如何把参数用Soap封装起来发出去,并获取结果。服务端只关心如何对Soap进行拆包->服务->封包。gSOAP可以帮我们实现上述过程中的拆包和封包,而我们可以只关心服务的实现。

言归正传,在这里我们以一个简单的实现加、减、开放的Web Services的服务为例子,介绍gSOAP的使用:
为了发布这个Web服务,首先我们需要把服务的接口定义好,这个服务可能是一个现有服务的Adapter,为此我们定义头文件
calc.h:
typedef double xsd__double;
int ns__add(xsd__double a, xsd__double b, xsd__double &result);
int ns__sub(xsd__double a, xsd__double b, xsd__double &result);
int ns__sqrt(xsd__double a, xsd__double &result); 
注意到这里面我们把double定义成了xsd__double(两个下划线),这是为了告诉gSOAP,我们需要的soap格式和WSDL格式是基于Document/literal的而非rpc/encoded.为了不把事情搞复杂,在这里我只能说,Java1.6自带的Web Services工具只支持Document/literal格式的WSDL,所以我们生成这种格式的WSDL。至于这两种格式之间选择和他们的long story,大家可以参考下面的文章:
http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/
编写好头文件后,我们就可以利用gSOAP提供的工具进行生成了:
/usr/lib/gsoap-2.7/bin/soapcpp2 -S -2 calc.h
生成的主要文件详见附件。
下面我们实现calc.h中定义的函数:
// Contents of file "calc.cpp": 
#include "soapH.h" 
#include 
"ns.nsmap" 
#include 
<math.h> 
int main()
{
   struct soap soap;
   
int m, s; // master and slave sockets
   soap_init(&soap);
   m 
= soap_bind(&soap, "localhost"9999100);
   
if (m < 0)
      soap_print_fault(
&soap, stderr);
   
else
   {
      fprintf(stderr, 
"Socket connection successful: master socket = %d\n", m);
      
for (int i = 1; ; i++)
      {
         s 
= soap_accept(&soap);
         
if (s < 0)
         {
            soap_print_fault(
&soap, stderr);
            
break;
         }
         fprintf(stderr, 
"%d: accepted connection from IP=%d.%d.%d.%d socket=%d", i,
            (soap.ip 
>> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
         
if (soap_serve(&soap) != SOAP_OK) // process RPC request
            soap_print_fault(&soap, stderr); // print error
         fprintf(stderr, "request served\n");
         soap_destroy(
&soap); // clean up class instances
         soap_end(&soap); // clean up everything and close socket
      }
   }
   soap_done(
&soap); // close master socket and detach environment
}
// Implementation of the "add" remote method: 
int ns__add(struct soap *soap, double a, double b, double &result) 

   result 
= a + b; 
   
return SOAP_OK; 

// Implementation of the "sub" remote method: 
int ns__sub(struct soap *soap, double a, double b, double &result) 

   result 
= a - b; 
   
return SOAP_OK; 

// Implementation of the "sqrt" remote method: 
int ns__sqrt(struct soap *soap, double a, double &result) 

   
if (a >= 0
   { 
      result 
= sqrt(a); 
      
return SOAP_OK; 
   } 
   
else
   { 
      
return soap_sender_fault(soap, "Square root of negative value""I can only compute the square root of a non-negative value");
   } 
前文提到过,我们不希望为了发布基于Web Services的C语言的API而开发或应用一个大的Web服务器。我们代码中的main函数实现了一个最简单的Web Server(基于Socket).这个Server利用gSOAP生成的API来提供针对SOAP的处理。
下面我们把这个嵌入式的web server编译,编译的时候注意stdsoap2.cpp这个文件是从gSOAP包中拷贝而来,不是自动生成的,大家下载gSOAP后直接就能找到这个文件及其头文件。
g++ -o calcServer calc.cpp soapC.cpp soapServer.cpp stdsoap2.cpp
一个以Web Servers形式提供的C API诞生了。
在server端执行./calcServer

下面讨论如何用Java1.6的自带工具生成一个客户端stub:
把gSOAP生成的WSDL拷贝到我们的Java开发环境中来,按照Web Services Server中定义的端口和服务器,配置参数生成客户端Web Services代码:
/usr/lib/jvm/jdk1.6.0_03/bin/wsimport -extension -httpproxy:localhost:9999 -verbose ns.wsdl

生成后,把这个环境添加到eclipse的编译环境中来,然后在eclipse中建一个新的类:
class Test {
    
public static void main(String args[]) {
        Service service 
= new Service();
        
double h = service.getService().sub(200001);
        System.out.println(h);
    }
}
运行后得到结果19999.0

总结:当集成Java和C两种平台时,我们可以有多种解决方案,但首先我们应该想到gSOAP因为它能够很出色地完成任务。
文中相关代码:
http://www.blogjava.net/Files/yangyi/gsoap.zip
广告:本人明年毕业,正在找工作,个人简历:
http://www.blogjava.net/Files/yangyi/My%20Resume.zip


 @2008 杨一. 版权所有. 保留所有权利

posted on 2007-12-06 12:19 杨一 阅读(1745) 评论(2)  编辑  收藏 所属分类: Java SE

评论

# re: 浅谈Java中的通信机制及与C/C++ API的集成(下) 2008-05-07 17:06 唐为奇

为什么eclipse里无法识别import localhost._80.service.Service;
出现The import localhost cannot be resolved问题啊,请指教啊!  回复  更多评论   

# re: 浅谈Java中的通信机制及与C/C++ API的集成(下)[未登录] 2008-12-29 17:15 tom

请问博主,客户端是如何发现服务器端提供的服务的,能否结合你这里的例子说明一下。非常感谢!  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2007年12月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

公告

本人在blogjava上发表的文章及随笔除特别声明外均为原创或翻译,作品受知识产权法保护并被授权遵从 知识分享协议:署名-非商业性使用-相同方式共享 欢迎转载,请在转载时注明作者姓名(杨一)及出处(www.blogjava.net/yangyi)
/////////////////////////////////////////
我的访问者

常用链接

留言簿(5)

随笔分类(55)

随笔档案(55)

相册

Java

其他技术

生活

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜

自强不息


用心 - 珍惜时间,勇于创造