加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

gsoap使用心得!

发布时间:2020-12-17 00:38:31 所属栏目:安全 来源:网络整理
导读:From: http://www.cppblog.com/qiujian5628/archive/2008/06/19/54019.html 完整源码 下载 最近换了个工作环境,现在在大望路这边上班,呵,刚上班接到的任务就是熟悉gsoap!废话少说,现在开始gSoap学习! gSOAP 是一个夸平台的,用于开发 Web Service 服务

From: http://www.cppblog.com/qiujian5628/archive/2008/06/19/54019.html


完整源码下载

最近换了个工作环境,现在在大望路这边上班,呵,刚上班接到的任务就是熟悉gsoap!废话少说,现在开始gSoap学习!

gSOAP是一个夸平台的,用于开发Web Service服务端和客户端的工具,在WindowsLinuxMAC OSUNIX下使用CC++语言编码,集合了SSL功能。

下载地址:http://www.voidcn.com/tag/http://sourceforge.net/projects/gsoap2

官方网站:http://www.voidcn.com/tag/http://genivia.com/Products/gsoap/index.html

对于Windows平台下开发客户端,首先下载最新的gsoap_win32_2.7.6c.zip包,具体在以下地址:http://optusnet.dl.sourceforge.net/sourceforge/gsoap2/gsoap_win32_2.7.6c.zip

首先查看gsoap的User's Guide,基本就能对gsoap有个全面的了解,通过阅读Sample里的例子程序深入。然后搜索网上其它一些文章,比如:
gSOAP简单多线程服务器程序 http://blog.chinaunix.net/u1/55091/showart_430965.html
纯c gSoap实现WebService??????????? http://hi.baidu.com/2sky2sea/blog/item/40ec5555680279c1b745ae9b.html?


接下来我结合自己的实践与理解,讲讲VC用gsoap下编写webService和客户端程序,有不对的地方还请大家指正,谢谢。
我以网上出现的实现一个简单的加法函数为例,讲讲我在操作过程中遇到的问题。

一 服务器端
1.首先编写 add.h文件:
1

// gsoap?ns?service?name:?add
2

// gsoap?ns?service?namespace:? http://localhost/add.wsdl
3

// gsoap?ns?service?location:? http://localhost
4

// gsoap?ns?service?executable:?add.cgi
5

// gsoap?ns?service?encoding:?encoded
6

// gsoap?ns?schema?namespace:?urn:add
7


8

int ?ns__add(? int ?num1,? int ?num2,? int * ?sum?);
9


2.用gsoap/bin目录下的soapcpp2.exe程序,生成一些文件。可以把soapcpp2.exe拷贝到一add.h目录下,用cmd执行soapcpp2.exe add.h就可以,在这个目录下会自动生成许多将来有用的文件,如add.namap,soapH.h,soapC.cpp,soapClient.cpp,soapServer.cpp等文件。soapcpp2.exe可以带参数执行,具体执行soapcpp2.exe -h查看。

3.新建一个win32控制台工程,加入wsock32.lib库,将刚才生成的那些文件添加到工程中。然后编写webserver.cpp主程序:

#include? " add.h "

#include?
" add.nsmap "


int ?main( int ?argc,? char * ?argv[])

{

????

????
int?m,?s;?/*?master?and?slave?sockets?*/

????
struct?soap?add_soap;

????soap_init(
&add_soap);

????
//soap_set_namespaces(&add_soap,?add_namespaces);

????

????
if?(argc?<?2)

????
{

????????printf(
"usage:?%s?<server_port>?n",?argv[0]);

????????exit(
1);

????}

????
else

????
{?

????????m?
=?soap_bind(&add_soap,?NULL,?atoi(argv[1]),?100);

????????
if?(m?<?0)

????????
{

????????????soap_print_fault(
&add_soap,?stderr);

????????????exit(
-1);

????????}

????????

????????fprintf(stderr,?
"Socket?connection?successful:?master?socket?=?%dn",?m);

????????
for?(?;?;?)

????????
{?

????????????s?
=?soap_accept(&add_soap);?

????????????
if?(s?<?0)

????????????
{?

????????????????soap_print_fault(
&add_soap,?stderr);

????????????????exit(
-1);

????????????}

????????????fprintf(stderr,?
"Socket?connection?successful:?slave?socket?=?%dn",?s);

????????????

????????????soap_serve(
&add_soap);//该句说明该server的服务

????????????soap_end(&add_soap);

????????}

????}

????
return?0;

}

// server端的实现函数与add.h中声明的函数相同,但是多了一个当前的soap连接的参数

int ?ns__add( struct ?soap? * add_soap,? int ?num1,? int ? * sum)

{

????
*sum?=?num1?+?num2;

????
return?0;

}


4. 编译这个程序,会提示错误,将gsoap_win32目录下stdsoap2.cpp,stdsoap2.h文件加入工程,重新编译如果还有错误,可能是你将add.h生成的文件添加入工程出错的原因。实际上在编写server程序时,无须带Client的那些文件,还有带Lib的文件也无须添加到工程中。再重新编译应该就没有问题了,启动4567端口,在ie中输入localhost:4567,如果显示xml页面,说明程序已经启动。

二 对应的客户端
1。客户端程序代码如下:

#include? < stdio.h >

#include?
< stdlib.h >

#include?
" soapH.h "

#include?
" add.nsmap "



int ?add( const ? char * ?server,? int ? * sum);


int ?main( int ?argc,? char ? ** argv)?

{

????
int?result?=?-1;

????
char*?server="http://localhost:4567";

????
int?num1?=?0;

????
int?num2?=?0;

????
int?sum?=?0;

????
if(?argc?<?3?)

????
{

????????printf(
"usage:?%s?num1?num2?n",?argv[0]);

????????exit(
0);

????}

????

????num1?
=?atoi(argv[1]);

????num2?
=?atoi(argv[2]);

????

????result?
=?add(server,?num1,?num2,?&sum);

????
if?(result?!=?0)

????
{

????????printf(
"soap?err,errcode?=?%dn",?result);

????}

????
else

????
{

????????printf(
"%d+%d=%dn",?sum?);

????}

????
return?0;

}


int ?add(? const ? char * ?server,? int ? * sum?)

{

????
struct?soap?add_soap;

????
int?result?=?0;

????soap_init(
&add_soap);

//????soap_set_namespaces(&add_soap,?add_namespaces);

????

????
//该函数是客户端调用的主要函数,后面几个参数和add.h中声明的一样,前面多了3个参数,函数名是接口函数名ns__add前面加上soap_call_

????soap_call_ns__add(?&add_soap,?server,?"",?sum?);

????
if(add_soap.error)

????
{

????????printf(
"soap?error:%d,%s,%sn",?add_soap.error,?*soap_faultcode(&add_soap),?*soap_faultstring(&add_soap)?);

????????result?
=?add_soap.error;

????}
?

????soap_end(
&add_soap);

????soap_done(
&add_soap);

????
return?result;

}

2.客户端程序既可以新建一个新的win32控制台程序,将刚才生成的nsmap,soapClient.h等文件加入工程,编译既可。我是直接在原先工程中加入一客户端代码,将webserver.cpp文件移除,并且将soapServer.cpp等server端需要的文件移除,将soapClient.cpp等client端需要的cpp添加到工程,编译既可。
3.启动server程序,F5客户端程序,经测试正常。

三 遇到的问题
1.server端可以编译成CGI方式执行,而并不是绑定到某个端口,这种方式我没有实践。

if ?(argc? < ? 2 )? // ?no?args:?assume?this?is?a?CGI?application?

??? {?

??????soap_serve(
&soap);?//?serve?request,?one?thread,?CGI?style?

??????soap_destroy(&soap);?//?dealloc?C++?data?

??????soap_end(&soap);?//?dealloc?data?and?clean?up?

}
2.在编译服务器及客户端程序时一开始对add.h生成的文件添加到工程,经常出现问题,需要自己不调试。特别是链接时段,server/client要与其生成的文件相对应,server调用生成的soapserver.cpp,client调用生成的soapclient.cpp文件。
3.多线程方式,在windows下建议用pthread_win32库,这里给出多线程下的例子。

一?gSOAP需要的头文件:


// gsoap?ns?service?name:?calc

// gsoap?ns?service?style:?rpc

// gsoap?ns?service?encoding:?encoded

// gsoap?ns?service?namespace:? http://127.0.0.1 :8089/calc.wsdl

// gsoap?ns?service?location:? http://127.0.0.1 :8089/cal

// gsoap?ns?schema??namespace:????urn:calc

int ?ns__add( double ?a,? double ?b,? double ? * result);

int ?ns__sub( double ?a,? double ? * result);

int ?ns__mul( double ?a,? double ? * result);

int ?ns__div( double ?a,? double ? * result);

int ?ns__pow( double ?a,? double ? * result);


二?多线程服务器关键代码


#include?

#include??
" calc.nsmap "

#include??
" soapH.h "


/////////////////////////////////////////////////////////////////////////

///宏与全局变量的定义

#define ??BACKLOG?(100)??

#define ??MAX_THR?(10)???

#define ??MAX_QUEUE?(1000)



pthread_mutex_t?queue_cs;????????????????????????
// 队列锁

pthread_cond_t??queue_cv;?????????????????????????? // 条件变量

SOAP_SOCKET?????queue[MAX_QUEUE];??? // 数组队列

int ???????????????????????????head? = 0 ,?tail? = 0 ;?????????? // 队列头队列尾初始化?????????

//////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////

void ? * ??????process_queue( void ? * );???????? // 线程入口函数

int ?????????enqueue(SOAP_SOCKET);?? // 入队列函数

SOAP_SOCKET?dequeue( void );????????? // 出队列函数


//////////////////////////////////////////////////////////////////////////

// 线程入口函数

void ? * ?process_queue( void ? * ?soap)

{

??
struct?soap?*?tsoap?=?(struct?soap?*)soap;

??
for(;;)

??
{

????????tsoap
->socket?=?dequeue();

????????
if?(!soap_valid_socket(tsoap->socket))

???????
{

?????????
break;

????????}

????????soap_serve(tsoap);

????????soap_destroy(tsoap);

????????soap_end(tsoap);

??}

??
return?NULL;

}


// 入队列操作

int ?enqueue(SOAP_SOCKET?sock)

{

??
int?status?=?SOAP_OK;

??
int?next;

??pthread_mutex_lock(
&queue_cs);

??next?
=?tail?+1;

??
if?(next?>=?MAX_QUEUE)?

????next?
=?0;

??
if?(next?==?head)?

??????status?
=?SOAP_EOM;

??
else

??
{

????queue[tail]?
=sock;

????tail?
=?next;

??}

??pthread_cond_signal(
&queue_cv);

??pthread_mutex_unlock(
&queue_cs);

??
return?status;

}


// 出队列操作

SOAP_SOCKET?dequeue()

{

??SOAP_SOCKET?sock;

??pthread_mutex_lock(
&queue_cs);

???
while?(head?==?tail?)

???
{

??????????pthread_cond_wait(
&queue_cv,&queue_cs);

???}

??sock?
=?queue[head++];

??
if?(head?>=?MAX_QUEUE)

????????
{

????head?
=0;

??}

??pthread_mutex_unlock(
&queue_cs);

??
return?sock;

}



//////////////////////////具体服务方法////////////////////////////////////////

// 加法的实现

int ?ns__add( struct ?soap? * soap,? double ?a,? double ? * result)

{

??????
*result?=?a?+?b;

??????
return?SOAP_OK;

}
?

// 减法的实现

int ?ns__sub( struct ?soap? * soap,? double ? * result)

{?

?????
*result?=?a?-?b;

?????
return?SOAP_OK;

}
?

// 乘法的实现

int ?ns__mul( struct ?soap? * soap,? double ? * result)

{?

?????
*result?=?a?*?b;

?????
return?SOAP_OK;

}
?

// 除法的实现

int ?ns__div( struct ?soap? * soap,? double ? * result)

{?

???
if?(b)

???????
*result?=?a?/?b;

???
else

??
{

?????????
char?*s?=?(char*)soap_malloc(soap,?1024);

?????????sprintf(s,?
"Can't">http://tempuri.org/">Can't?divide?%f?by?%f",?a,?b);

?????????return?soap_sender_fault(soap,?"Division?by?zero",?s);

??}

??
return?SOAP_OK;

}
?

// 乘方的实现

int ?ns__pow( struct ?soap? * soap,? double ? * result)

{?

??
*result?=?pow(a,?b);

??
if?(soap_errno?==?EDOM)?/*?soap_errno?和errorno类似,?但是和widnows兼容?*/

??
{?

????
char?*s?=?(char*)soap_malloc(soap,?1024);

????sprintf(s,?
"Can't?take?the?power?of?%f?to??%f",?b);

????sprintf(s,?
"Can't">http://tempuri.org/">Can't?take?power?of?%f?to?%f",?b);

????return?soap_sender_fault(soap,?"Power?function?domain?error",?s);

??}

??
return?SOAP_OK;

}
?


//////////////////////////////////////////////////////////////////////////////////////////////////////

// 主函数

int ?main( int ?argc, char ? ** ?argv)

{

??
struct?soap?ServerSoap;

?????
//初始话运行时环境

????soap_init(&ServerSoap);

????
//如果没有参数,当作CGI程序处理

????if?(argc?<2)?

????
{???????

???????????
//CGI?风格服务请求,单线程

??????????soap_serve(&ServerSoap);

??????????
//清除序列化的类的实例

?????????soap_destroy(&ServerSoap);

?????????
//清除序列化的数据

????????soap_end(&ServerSoap);?????

???}
else

???
{

?????
struct?soap?*?soap_thr[MAX_THR];

?????pthread_t?tid[MAX_THR];

?????
int?i,port?=?atoi(argv[1]);

?????SOAP_SOCKET?m,s;

??????
//锁和条件变量初始化

?????pthread_mutex_init(&queue_cs,NULL);

?????pthread_cond_init(
&queue_cv,NULL);

?????
//绑定服务端口

????m?=?soap_bind(&ServerSoap,NULL,port,BACKLOG);

????
//循环直至服务套接字合法

????while?(!soap_valid_socket(m))

???
{

????????????????fprintf(stderr,
"Bind?port?error!?");

????????????????m?
=?soap_bind(&ServerSoap,BACKLOG);

????}

????fprintf(stderr,
"socket?connection?successful?%d?",m);

????????????????

?????
//生成服务线程

????for(i?=?0;?i?<MAX_THR;?i++)


???
{

??????soap_thr[i]?
=?soap_copy(&ServerSoap);

??????fprintf(stderr,
"Starting?thread?%d?",i);

??????pthread_create(
&tid[i],(void*(*)(void*))process_queue,(void*)soap_thr[i]);

????}

????????????????

????
for(;;)

????
{

??????
//接受客户端的连接

??????s?=?soap_accept(&ServerSoap);

??????
if?(!soap_valid_socket(s))?

??????
{

????????
if?(ServerSoap.errnum)?

????????????????????????????????
{

??????????soap_print_fault(
&ServerSoap,stderr);

??????????
continue;

????????}
else

????????
{

??????????fprintf(stderr,
"Server?timed?out?");

??????????
break;

????????}

??????}

???????
//客户端的IP地址

??????fprintf(stderr,"Accepted?connection?from?IP=?%d.%d.%d.%d?socket?=?%d?",

???????????????????????????????((ServerSoap.ip)
>>24)&0xFF,((ServerSoap.ip)>>16)&0xFF,((ServerSoap.ip)>>8)&0xFF,(ServerSoap.ip)&0xFF,(ServerSoap.socket));

??????
//请求的套接字进入队列,如果队列已满则循环等待

???????while(enqueue(s)?==?SOAP_EOM)

????????????????Sleep(
1000);

????}

????
//服务结束后的清理工作

????for(i?=?0;?i?<?MAX_THR;?i++)

????
{

??????
while?(enqueue(SOAP_INVALID_SOCKET)?==?SOAP_EOM)?

???????
{

???????????Sleep(
1000);

??????}

????}

????
for(i=0;?i<?MAX_THR;?i++)

????
{

??????fprintf(stderr,
"Waiting?for?thread?%d?to?terminate?..",i);

??????pthread_join(tid[i],NULL);

??????fprintf(stderr,
"terminated?");

??????soap_done(soap_thr[i]);

??????free(soap_thr[i]);

????}

????pthread_mutex_destroy(
&queue_cs);

????pthread_cond_destroy(
&queue_cv);

??}

????
//分离运行时的环境

??soap_done(&ServerSoap);

??
return?0;

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读