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

gsoap使用心得

发布时间:2020-12-17 00:03:07 所属栏目:安全 来源:http://www.voidcn.com/tag/http
导读: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/ta


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(? ?num1,? ?num2,0)">* ?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


?main( ?argc,255)">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[]),?100);

????????
?(m?)

????????
{

????????????soap_print_fault(

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

????????}

????????

????????fprintf(stderr,0)">Socket?connection?successful:?master?socket?=?%d/n

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

????????
{?

????????????s?
?soap_accept(add_soap);?

????????????
?(s?)

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

????????????????soap_print_fault(

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

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

????????????fprintf(stderr,0)">Socket?connection?successful:?slave?socket?=?%d/n

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

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

????????}

????}
return;

}

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

{

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

????


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

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

< stdio.h > stdlib.h soapH.h



?add( const ?server,0)">sum);


** argv)?

?result?;

????
char?serverhttp://localhost:4567?num2??sum?(?argc?3?)

????
usage:?%s?num1?num2?/n

????

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

????num2?
]);

????

????result?
?add(server,?num1,?num2,0)">sum);

????
?(result?!=)

????
soap?err,errcode?=?%d/n

????}

????
%d+%d=%d/n

????}
?add(? sum?)

?soap?add_soap;

????
;

????soap_init(
add_soap);

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

????

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

????
(add_soap.error)

????
soap?error:%d,%s,%s/nsoap_faultcode(add_soap),0)">soap_faultstring(add_soap)?);

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

????}
?

????soap_end(
add_soap);

????soap_done(
?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(?dealloc?C++?data???????soap_end(?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

http://127.0.0.1 :8089/calc.wsdl

:8089/cal

gsoap?ns?schema??namespace:????urn:calc double ?a,0)">?b,0)">result);

?ns__sub( ?ns__mul( ?ns__div( ?ns__pow( result);


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


#include?

#include??
calc.nsmap

#include??


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

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

#define ??BACKLOG?(100)?? ??MAX_THR?(10)??? ??MAX_QUEUE?(1000)



pthread_mutex_t?queue_cs;????????????????????????
队列锁 pthread_cond_t??queue_cv;?????????????????????????? 条件变量 SOAP_SOCKET?????queue[MAX_QUEUE];??? 数组队列 ???????????????????????????head? = 0 ;?????????? 队列头队列尾初始化?????????

//



//

void ??????process_queue( );???????? 线程入口函数 ?????????enqueue(SOAP_SOCKET);?? 入队列函数 SOAP_SOCKET?dequeue( );????????? 出队列函数

?process_queue( ?soap)

{

??
?soap??tsoap??()soap;

??
(;;)

??
{

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

????????
!soap_valid_socket(tsoapsocket))

???????
{

?????????
break;

????????}

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

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

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

??}

??
?NULL;

}
入队列操作 ?enqueue(SOAP_SOCKET?sock)

?status??SOAP_OK;

??
?next;

??pthread_mutex_lock(
queue_cs);

??next?
?tail?;

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

????next?
==?head)?

??????status?
?SOAP_EOM;

??

??
{

????queue[tail]?
sock;

????tail?
?next;

??}

??pthread_cond_signal(
queue_cv);

??pthread_mutex_unlock(
queue_cs);

??
?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++];

??
?MAX_QUEUE)

????????
{

????head?
;

??}

??pthread_mutex_unlock(
?sock;

}



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

加法的实现 soap,0)">result)

{

??????
result??a??b;

??????
?SOAP_OK;

}
?

减法的实现 result)

{?

?????
?b;

?????
乘法的实现 result)

除法的实现 result)

{?

???
?(b)

???????
/?b;

???

??
s?)soap_malloc(soap,0)">1024);

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

??}
乘方的实现 result)

{?

??
?pow(a,?b);

??
?(soap_errno??EDOM)??soap_errno?和errorno类似,?但是和widnows兼容?

??
{?

????
);

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

????sprintf(s,0)">tempuri.org/">Can't?take?power?of?%f?to?%f",0)">????
Power?function?domain?error?


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

主函数 ?argv)

?soap?ServerSoap;

?????
初始话运行时环境????soap_init(ServerSoap);

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

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

???????????
CGI?风格服务请求,单线程??????????soap_serve(ServerSoap);

??????????
清除序列化的类的实例?????????soap_destroy(ServerSoap);

?????????
清除序列化的数据????????soap_end(ServerSoap);?????

???}

???
{

?????
?soap_thr[MAX_THR];

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

?????
?i,port?]);

?????SOAP_SOCKET?m,s;

??????
锁和条件变量初始化?????pthread_mutex_init(queue_cs,NULL);

?????pthread_cond_init(

?????
绑定服务端口????m?ServerSoap,NULL,port,BACKLOG);

????
循环直至服务套接字合法soap_valid_socket(m))

???
{

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

????????????????m?

????}

????fprintf(stderr,0)">socket?connection?successful?%d?

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

?????
生成服务线程(i?;?i?MAX_THR;?i)


???
{

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

??????fprintf(stderr,0)">Starting?thread?%d?

??????pthread_create(
tid[i],(void()())process_queue,0)">)soap_thr[i]);

????}

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

????
(;;)

????
接受客户端的连接??????s?ServerSoap);

??????
soap_valid_socket(s))?

??????
{

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

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

??????????soap_print_fault(

??????????
continue

????????
{

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

??????????

??????}

???????
客户端的IP地址??????fprintf(stderr,0)">Accepted?connection?from?IP=?%d.%d.%d.%d?socket?=?%d?

???????????????????????????????((ServerSoap.ip)
>>24)&&0xFF168

??????
请求的套接字进入队列,如果队列已满则循环等待???????(enqueue(s)??SOAP_EOM)

????????????????Sleep(
1000服务结束后的清理工作?MAX_THR;?i)

????
?(enqueue(SOAP_INVALID_SOCKET)??SOAP_EOM)?

???????
{

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

??????}
(i;?i)

????
{

??????fprintf(stderr,0)">Waiting?for?thread?%d?to?terminate?..

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

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

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

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

????}

????pthread_mutex_destroy(
queue_cs);

????pthread_cond_destroy(
queue_cv);

??}
分离运行时的环境??soap_done(ServerSoap);

??
;

}

(编辑:李大同)

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

    推荐文章
      热点阅读