C++与Java的一种webservice通信方式实现记录直接分享了. 代码工程
C++采用gsoap库来实现的,在gsoap的SDK中可以找到两个将接口生成代码框架的工具,soapcpp2.exe wsdl2h.exe
服务端例子add.h
//gsoap ns service name: add
//gsoap ns service namespace: http://localhost/add.wsdl
//gsoap ns service location: http://localhost
//gsoap ns service executable: add.cgi
//gsoap ns service encoding: encoded
//gsoap ns schema namespace: urn:add
int ns__add(int a, int b, int *result);
int ns__sub(double a, double b, double *result);
int ns__mul(double a, double b, double *result);
int ns__div(double a, double b, double *result);
int ns__pow(double a, double b, double *result);
//int ns__checkLogin(char* Name,char* Pass, bool *result);
//int ns__TestShow(int *id, char* *result);
int ns__ClsP(int *result);
int ns__HahaKd(int *result);
int ns__EndExe(char* Name, int *result);
int ns__StartExe(char* Name, int *result);
服务端代码:
#include "DCSoap.h"
//输出DBdata的soap
//#include "Soap/soapH.h"
//#include "Soap/DBdata.h"
//输出add的soap
/*#include "lib/add.nsmap"*/
#include "../Soap/soapH.h"
#include "../Soap/add.h"
#include <iostream>
using namespace std;
#define BACKLOG (100) /* Max. request backlog */
DWORD WINAPI process_request(LPVOID*);
int http_get(struct soap * soap);
DWORD WINAPI process_request(LPVOID* soap)
{
soap_serve((struct soap*)soap);
soap_destroy((struct soap*)soap);
soap_end((struct soap*)soap);
soap_done((struct soap*)soap);
free(soap);
return 0;
}
int http_get(struct soap * soap)
{
FILE *fd = NULL;
cout<<"call http_get."<<endl; //printf("call http_get.\n");
char *s = strchr(soap->path, '?');
if ( !s || strcmp(s, "?wsdl") ) return SOAP_GET_METHOD;
//fopen_s(&fd,"DBdata.wsdl", "rb");
fopen_s(&fd,"add.wsdl", "rb");
//fd = fopen("add.wsdl", "rb"); //vc6
if ( !fd ) return 404;
soap->http_content = "text/xml";
soap_response(soap, SOAP_FILE);
for ( ; ; ) {
size_t r = fread(soap->tmpbuf, 1, sizeof(soap->tmpbuf), fd);
if ( !r ) break;
if ( soap_send_raw(soap, soap->tmpbuf, r) ) break;
}
fclose(fd);
soap_end_send(soap);
return SOAP_OK;
}
int main(int Cport)
{
struct soap soap;
struct soap *tsoap;
const char* fmt = "accepts socket %d connection from IP %d.%d.%d.%d\n";
soap_init(&soap);
int port;
port = Cport; //atoi(argv[1]);
cout<<"OPEN HTTP://127.0.0.1:"<<Cport<<endl; //printf("OPEN HTTP://127.0.0.1:80 \n", Cport);
soap.send_timeout = 60;
soap.recv_timeout = 60;
soap.accept_timeout = 3600;
soap.max_keep_alive = 100;
soap.fget = http_get;
DWORD tid;
HANDLE hThread;
//int port = atoi(argv[1]); // first command-line arg is port
SOAP_SOCKET m, s;
m = soap_bind(&soap, NULL, port, BACKLOG);
if ( !soap_valid_socket(m) )
{
cout<<"Sorry! The port is userd!"<<endl;
//exit(1);
return 0;
}
cout<<"Socket connection successful "<<m<<endl; //
for ( ; ; )
{
s = soap_accept(&soap);
if ( !soap_valid_socket(s) )
{
if ( soap.errnum )
{
soap_print_fault(&soap, stderr);
//exit(1);
return 0;
}
cout<<"server timed out"<<endl; //printf("server timed out\n");
break;
}
printf(fmt, s, (soap.ip>>24)&0xFF, (soap.ip>>16)&0xFF, (soap.ip>>8)&0xFF, soap.ip&0xFF);
tsoap = soap_copy(&soap); // make a safe copy
if ( !tsoap ) break;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)process_request, tsoap, 0, &tid);
if ( hThread == NULL )
{
cout<<"can not create a thread for SOAP request processing."<<endl;
//printf("can not create a thread for SOAP request processing.\n");
//exit(-1);
return 0;
}
}
soap_done(&soap);
return 0;
}
HANDLE SoapThreadHandle;
DWORD SoapThreadID;
void TheardSoapSvr(int Cport)
{
SoapThreadHandle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)StartSoapServer,(void*)Cport,0,&SoapThreadID);
CloseHandle(SoapThreadHandle); //上面线程完成后自动释放线程
}
void EndTheardSoapSvr(void)
{
//ExitThread(SoapThreadHandle);
}
生成wsdl接口文件的方法:
rem wsdl2h.exe: 编译wsdl文件生成c/c++头文件
rem -o 文件名,指定输出头文件
rem -n 名空间前缀 代替默认的ns
rem -c 产生纯C代码,否则是C++代码
rem -s 不要使用STL代码
rem -t 文件名,指定type map文件,默认为typemap.dat
rem -e 禁止为enum成员加上名空间前缀
rem soapcpp2.exe: gSOAP编译器,
rem 编译头文件生成服务器和客户端都需要的c/c++文件
rem -C 仅生成客户端代码
rem -S 仅生成服务器端代码
rem -L 不要产生soapClientLib.c和soapServerLib.c文件
rem -c 产生纯C代码,否则是C++代码(与头文件有关)
rem -I 指定import路径(见上文)
rem -x 不要产生XML示例文件
rem -i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)
attrib +r +h +s add.cpp
attrib +r +h +s add.h
del *.xml
del *.o
del *.h
del *.cpp
del *.nsmap
del *.xsd
del *.wsdl
rd /s /q client
rem 生成服务端代码
rem gsoap\bin\win32\soapcpp2.exe -S -I gsoap\import Csoap\lib\add.h
gsoap\bin\win32\soapcpp2.exe add.h
rem gsoap\bin\win32\soapcpp2.exe -i add.h
rem 生成客户端代码
md client
copy /Y add.h .\client\
rem gsoap\bin\win32\wsdl2h.exe -o client\add.h add.wsdl
rem #gsoap\bin\win32\soapcpp2.exe -C -I gsoap\import client\add.h
rem #gsoap\bin\win32\wsdl2h.exe -o add.h ..\..\exe\add.wsdl
attrib -r -h -s add.cpp
attrib -r -h -s add.h
@copy /Y add.wsdl ..\exe\
pause
这里客户端请求 我还是用C++代码(java的应该很常见了)
客户端就是拿到wsdl接口文件去生成代码了
@echo off
rem wsdl2h.exe: 编译wsdl文件生成c/c++头文件
rem -o 文件名,指定输出头文件
rem -n 名空间前缀 代替默认的ns
rem -c 产生纯C代码,否则是C++代码
rem -s 不要使用STL代码
rem -t 文件名,指定type map文件,默认为typemap.dat
rem -e 禁止为enum成员加上名空间前缀
rem soapcpp2.exe: gSOAP编译器,
rem 编译头文件生成服务器和客户端都需要的c/c++文件
rem -C 仅生成客户端代码
rem -S 仅生成服务器端代码
rem -L 不要产生soapClientLib.c和soapServerLib.c文件
rem -c 产生纯C代码,否则是C++代码(与头文件有关)
rem -I 指定import路径(见上文)
rem -x 不要产生XML示例文件
rem -i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)
@echo off
del *.xml
del *.o
del *.h
del *.cpp
del *.nsmap
del *.xsd
del *.wsdl
cls
@echo on
copy /Y ..\..\exe\add.wsdl .\add.wsdl
..\..\Soap\gsoap\bin\win32\wsdl2h.exe -o add.h add.wsdl
..\..\Soap\gsoap\bin\win32\soapcpp2.exe -C -I ..\..\Soap\gsoap\import add.h
pause
客户端调用例子
// SoapClientConsole.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "SoapClient/soapH.h"
#include "SoapClient/soapStub.h"
#include "SoapClient/add.nsmap"
#include <string>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//int ns__add(int a, int b, int *result);
struct soap TestSoap;
soap_init(&TestSoap);
int result = -1;
_ns2__add input;
input.a = 1;
input.b = 1;
input.soap = &TestSoap;
_ns2__addResponse output;
output.soap = &TestSoap;
soap_call___ns1__add(&TestSoap,"http://127.0.0.1:80?wsdl",NULL,&input,&output); //"http://127.0.0.1:80?wsdl"
if(TestSoap.error)
{
printf("soap error:%d,%s,%s\n", TestSoap.error, *soap_faultcode(&TestSoap), *soap_faultstring(&TestSoap) );
result = TestSoap.error;
}
else
{
cout<<"Return = "<<*output.result<<endl;
}
soap_end(&TestSoap);
soap_done(&TestSoap);
system("pause");
return 0;
}
最后运行测试一下 只要IP对上跨机器通信也好使了.
