gSoap开发webservice client实例及详解_第1页
gSoap开发webservice client实例及详解_第2页
gSoap开发webservice client实例及详解_第3页
gSoap开发webservice client实例及详解_第4页
gSoap开发webservice client实例及详解_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

gSOAP是一个夸平台的,用于开发WebService服务端和客户端的工具,在Windows、Linux、MACOS和UNIX下使用C和C++语言编码,集合了SSL功能。

下载地址:/projects/gsoap2官方网站:/Products/gsoap/index.html对于Windows平台下开发客户端,首先下载最新的gsoap_win32_2.7.6c.zip包,具体在以下地址:/sourceforge/gsoap2/gsoap_win32_2.7.6c.zip首先查看gsoap的User'sGuide,基本就能对gsoap有个全面的了解,通过阅读Sample里的例子程序深入。然后搜索网上其它一些文章,比如:

gSOAP简单多线程服务器程序/u1/55091/showart_430965.html

纯cgSoap实现WebService

/2sky2sea/blog/item/40ec5555680279c1b745ae9b.html

接下来我结合自己的实践与理解,讲讲VC用gsoap下编写webService和客户端程序,有不对的地方还请大家指正,谢谢。

我以网上出现的实现一个简单的加法函数为例,讲讲我在操作过程中遇到的问题。一服务器端

1.首先编写add.h文件:

1//gsoapnsservicename:add

2//gsoapnsservicenamespace:

http://localhost/add.wsdl

3//gsoapnsservicelocation:

http://localhost

4//gsoapnsserviceexecutable:add.cgi

5//gsoapnsserviceencoding:encoded

6//gsoapnsschemanamespace:urn:add

7

8intns__add(intnum1,intnum2,int*sum);

9

2.用gsoap/bin目录下的soapcpp2.exe程序,生成一些文件。可以把soapcpp2.exe拷贝到一add.h目录下,用cmd执行soapcpp2.exeadd.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"intmain(intargc,char*argv[])

{

intm,s;/**//*masterandslavesockets*/

structsoapadd_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,"Socketconnectionsuccessful:mastersocket=%d/n",m);

for(;;)

{

s=soap_accept(&add_soap);

if(s<0)

{

soap_print_fault(&add_soap,stderr);

exit(-1);

}

fprintf(stderr,"Socketconnectionsuccessful:slavesocket=%d/n",s);

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

soap_end(&add_soap);

}

}

return0;

}

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

intns__add(structsoap*add_soap,intnum1,intnum2,int*sum)

{

*sum=num1+num2;

return0;

}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"

intadd(constchar*server,intnum1,intnum2,int*sum);intmain(intargc,char**argv)

{

intresult=-1;

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

intnum1=0;

intnum2=0;

intsum=0;

if(argc<3)

{

printf("usage:%snum1num2/n",argv[0]);

exit(0);

}

num1=atoi(argv[1]);

num2=atoi(argv[2]);

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

if(result!=0)

{

printf("soaperr,errcode=%d/n",result);

}

else

{

printf("%d+%d=%d/n",num1,num2,sum);

}

return0;

}intadd(constchar*server,intnum1,intnum2,int*sum)

{

structsoapadd_soap;

intresult=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,"",num1,num2,sum);

if(add_soap.error)

{

printf("soaperror:%d,%s,%s/n",add_soap.error,*soap_faultcode(&add_soap),*soap_faultstring(&add_soap));

result=add_soap.error;

}

soap_end(&add_soap);

soap_done(&add_soap);

returnresult;

}

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

3.启动server程序,F5客户端程序,经测试正常。三遇到的问题

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

if(argc<2)//noargs:assumethisisaCGIapplication

{

soap_serve(&soap);//serverequest,onethread,CGIstyle

soap_destroy(&soap);//deallocC++data

soap_end(&soap);//deallocdataandcleanup

}2.在编译服务器及客户端程序时一开始对add.h生成的文件添加到工程,经常出现问题,需要自己不调试。特别是链接时段,server/client要与其生成的文件相对应,server调用生成的soapserver.cpp,client调用生成的soapclient.cpp文件。

3.多线程方式,在windows下建议用pthread_win32库,这里给出多线程下的例子。

一gSOAP需要的头文件://gsoapnsservicename:calc

//gsoapnsservicestyle:rpc

//gsoapnsserviceencoding:encoded

//gsoapnsservicenamespace:

:8089/calc.wsdl

//gsoapnsservicelocation:

:8089/cal

//gsoapnsschema

namespace:

urn:calc

intns__add(doublea,doubleb,double*result);

intns__sub(doublea,doubleb,double*result);

intns__mul(doublea,doubleb,double*result);

intns__div(doublea,doubleb,double*result);

intns__pow(doublea,doubleb,double*result);二多线程服务器关键代码#include

#include

"calc.nsmap"

#include

"soapH.h"/**//////////////////////////////////////////////////////////////////////////

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

#define

BACKLOG(100)

#define

MAX_THR(10)

#define

MAX_QUEUE(1000)

pthread_mutex_tqueue_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_SOCKETdequeue(void);

//出队列函数/**///////////////////////////////////////////////////////////////////////////

//线程入口函数

void*process_queue(void*soap)

{

structsoap*tsoap=(structsoap*)soap;

for(;;)

{

tsoap->socket=dequeue();

if(!soap_valid_socket(tsoap->socket))

{

break;

}

soap_serve(tsoap);

soap_destroy(tsoap);

soap_end(tsoap);

}

returnNULL;

}//入队列操作

intenqueue(SOAP_SOCKETsock)

{

intstatus=SOAP_OK;

intnext;

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);

returnstatus;

}//出队列操作

SOAP_SOCKETdequeue()

{

SOAP_SOCKETsock;

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);

returnsock;

}

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

//加法的实现

intns__add(structsoap*soap,doublea,doubleb,double*result)

{

*result=a+b;

returnSOAP_OK;

}

//减法的实现

intns__sub(structsoap*soap,doublea,doubleb,double*result)

{

*result=a-b;

returnSOAP_OK;

}

//乘法的实现

intns__mul(structsoap*soap,doublea,doubleb,double*result)

{

*result=a*b;

returnSOAP_OK;

}

//除法的实现

intns__div(structsoap*soap,doublea,doubleb,double*result)

{

if(b)

*result=a/b;

else

{

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

sprintf(s,"Can't">/">Can'tdivide%fby%f",a,b);

returnsoap_sender_fault(soap,"Divisionbyzero",s);

}

returnSOAP_OK;

}

//乘方的实现

intns__pow(structsoap*soap,doublea,doubleb,double*result)

{

*result=pow(a,b);

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

{

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

sprintf(s,"Can'ttakethepowerof%fto

%f",a,b);

sprintf(s,"Can't">/">Can'ttakepowerof%fto%f",a,b);

returnsoap_sender_fault(soap,"Powerfunctiondomainerror",s);

}

returnSOAP_OK;

}/**///////////////////////////////////////////////////////////////////////////////////////////////////////

//主函数

intmain(intargc,char**argv)

{

structsoapServerSoap;

//初始话运行时环境

soap_init(&ServerSoap);

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

if(argc<2)

{

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

soap_serve(&ServerSoap);

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

soap_destroy(&ServerSoap);

//清除序列化的数据

soap_end(&ServerSoap);

}else

{

structsoap*soap_thr[MAX_THR];

pthread_ttid[MAX_THR];

inti,port=atoi(argv[1]);

SOAP_SOCKETm,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,"Bindporterror!");

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

}

fprintf(stderr,"socketconnectionsuccessful%d",m);

//生成服务线程

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

{

soap_thr[i]=soap_copy(&ServerSoap);

fprintf(stderr,"Startingthread%d",i);

pthread_create(&tid[i],NULL,(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,"Servertimedout");

break;

}

}

//客户端的IP地址

fprintf(stderr,"AcceptedconnectionfromIP=%d.%d.%d.%dsocket=%d",

((ServerSoap.ip)>>24)&&0xFF,((ServerSoap.ip)>>16)&0xFF,((ServerSoap.ip)>>8)&0xFF,(S

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论