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是一个夸平台的,用于开发Web Service服务端和客户端的工具,在Windows、Linux、MAC OS和UNIX下使用C和C++语言编码,集合了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?
2.在编译服务器及客户端程序时一开始对add.h生成的文件添加到工程,经常出现问题,需要自己不调试。特别是链接时段,server/client要与其生成的文件相对应,server调用生成的soapserver.cpp,client调用生成的soapclient.cpp文件。
??? {? ??????soap_serve(&soap);?//?serve?request,?one?thread,?CGI?style? ??????soap_destroy(&soap);?//?dealloc?C++?data? ??????soap_end(&soap);?//?dealloc?data?and?clean?up? } 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; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |