淺談Java中的通信機(jī)制及與C/C++ API的集成(下)
接著上次的話(huà)題,今天我們聊聊gSOAP這個(gè)框架,我們把用C寫(xiě)的舊有系統(tǒng)用gSOAP改造一下,通過(guò)SOA的形式發(fā)布出去。上文提到,利用gSOAP可以做到以下3點(diǎn):
1 一個(gè)Stand-alone的服務(wù)器外殼
2 一個(gè)根據(jù)API程序自動(dòng)生成的Web Services服務(wù)
3 一個(gè)WSDL描述符文件
客戶(hù)根據(jù) WSDL 描述文檔,會(huì)生成一個(gè) SOAP 請(qǐng)求消息。Web Services 都是放在Web服務(wù)器后面,客戶(hù)生成的SOAP請(qǐng)求會(huì)被嵌入在一個(gè)HTTP POST請(qǐng)求中,發(fā)送到 Web 服務(wù)器來(lái)。Web 服務(wù)器再把這些請(qǐng)求轉(zhuǎn)發(fā)給 Web Services 請(qǐng)求處理器。請(qǐng)求處理器的作用在于,解析收到的 SOAP 請(qǐng)求,調(diào)用 Web Services,然后再生成相應(yīng)的 SOAP 應(yīng)答。Web 服務(wù)器得到 SOAP 應(yīng)答后,會(huì)再通過(guò) HTTP應(yīng)答的方式把信息送回到客戶(hù)端。
WSDL是Web服務(wù)中客戶(hù)端和服務(wù)端溝通的橋梁,描述了對(duì)象提供的方法。SOAP幫我們制定了一份被官方認(rèn)可的對(duì)象的封裝方法。有了WSDL,客戶(hù)端只關(guān)心如何把參數(shù)用Soap封裝起來(lái)發(fā)出去,并獲取結(jié)果。服務(wù)端只關(guān)心如何對(duì)Soap進(jìn)行拆包->服務(wù)->封包。gSOAP可以幫我們實(shí)現(xiàn)上述過(guò)程中的拆包和封包,而我們可以只關(guān)心服務(wù)的實(shí)現(xiàn)。
言歸正傳,在這里我們以一個(gè)簡(jiǎn)單的實(shí)現(xiàn)加、減、開(kāi)放的Web Services的服務(wù)為例子,介紹gSOAP的使用:
為了發(fā)布這個(gè)Web服務(wù),首先我們需要把服務(wù)的接口定義好,這個(gè)服務(wù)可能是一個(gè)現(xiàn)有服務(wù)的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(兩個(gè)下劃線(xiàn)),這是為了告訴gSOAP,我們需要的soap格式和WSDL格式是基于Document/literal的而非rpc/encoded.為了不把事情搞復(fù)雜,在這里我只能說(shuō),Java1.6自帶的Web Services工具只支持Document/literal格式的WSDL,所以我們生成這種格式的WSDL。至于這兩種格式之間選擇和他們的long story,大家可以參考下面的文章: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);
http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/
編寫(xiě)好頭文件后,我們就可以利用gSOAP提供的工具進(jìn)行生成了:
/usr/lib/gsoap-2.7/bin/soapcpp2 -S -2 calc.h
生成的主要文件詳見(jiàn)附件。
下面我們實(shí)現(xiàn)calc.h中定義的函數(shù):
// 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", 9999, 100);
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");
}
}
前文提到過(guò),我們不希望為了發(fā)布基于Web Services的C語(yǔ)言的API而開(kāi)發(fā)或應(yīng)用一個(gè)大的Web服務(wù)器。我們代碼中的main函數(shù)實(shí)現(xiàn)了一個(gè)最簡(jiǎn)單的Web Server(基于Socket).這個(gè)Server利用gSOAP生成的API來(lái)提供針對(duì)SOAP的處理。#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", 9999, 100);
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");
}
}
下面我們把這個(gè)嵌入式的web server編譯,編譯的時(shí)候注意stdsoap2.cpp這個(gè)文件是從gSOAP包中拷貝而來(lái),不是自動(dòng)生成的,大家下載gSOAP后直接就能找到這個(gè)文件及其頭文件。
g++ -o calcServer calc.cpp soapC.cpp soapServer.cpp stdsoap2.cpp
一個(gè)以Web Servers形式提供的C API誕生了。
在server端執(zhí)行./calcServer
下面討論如何用Java1.6的自帶工具生成一個(gè)客戶(hù)端stub:
把gSOAP生成的WSDL拷貝到我們的Java開(kāi)發(fā)環(huán)境中來(lái),按照Web Services Server中定義的端口和服務(wù)器,配置參數(shù)生成客戶(hù)端Web Services代碼:
/usr/lib/jvm/jdk1.6.0_03/bin/wsimport -extension -httpproxy:localhost:9999 -verbose ns.wsdl
生成后,把這個(gè)環(huán)境添加到eclipse的編譯環(huán)境中來(lái),然后在eclipse中建一個(gè)新的類(lèi):
class Test {
public static void main(String args[]) {
Service service = new Service();
double h = service.getService().sub(20000, 1);
System.out.println(h);
}
}
運(yùn)行后得到結(jié)果19999.0public static void main(String args[]) {
Service service = new Service();
double h = service.getService().sub(20000, 1);
System.out.println(h);
}
}
總結(jié):當(dāng)集成Java和C兩種平臺(tái)時(shí),我們可以有多種解決方案,但首先我們應(yīng)該想到gSOAP因?yàn)樗軌蚝艹錾赝瓿扇蝿?wù)。
文中相關(guān)代碼:
http://www.aygfsteel.com/Files/yangyi/gsoap.zip
廣告:本人明年畢業(yè),正在找工作,個(gè)人簡(jiǎn)歷:
http://www.aygfsteel.com/Files/yangyi/My%20Resume.zip
@2008 楊一. 版權(quán)所有. 保留所有權(quán)利
posted on 2007-12-06 12:19 楊一 閱讀(1779) 評(píng)論(2) 編輯 收藏 所屬分類(lèi): Java SE