版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
gSOAP是一個(gè)夸平臺(tái)的,用于開(kāi)發(fā)WebService服務(wù)端和客戶端的工具,在Windows、Linux、MACOS和UNIX下使用C和C++語(yǔ)言編碼,集合了SSL功能。
下載地址:/projects/gsoap2官方網(wǎng)站:/Products/gsoap/index.html對(duì)于Windows平臺(tái)下開(kāi)發(fā)客戶端,首先下載最新的gsoap_win32_2.7.6c.zip包,具體在以下地址:/sourceforge/gsoap2/gsoap_win32_2.7.6c.zip首先查看gsoap的User'sGuide,基本就能對(duì)gsoap有個(gè)全面的了解,通過(guò)閱讀Sample里的例子程序深入。然后搜索網(wǎng)上其它一些文章,比如:
gSOAP簡(jiǎn)單多線程服務(wù)器程序/u1/55091/showart_430965.html
純cgSoap實(shí)現(xiàn)WebService
/2sky2sea/blog/item/40ec5555680279c1b745ae9b.html
接下來(lái)我結(jié)合自己的實(shí)踐與理解,講講VC用gsoap下編寫(xiě)webService和客戶端程序,有不對(duì)的地方還請(qǐng)大家指正,謝謝。
我以網(wǎng)上出現(xiàn)的實(shí)現(xiàn)一個(gè)簡(jiǎn)單的加法函數(shù)為例,講講我在操作過(guò)程中遇到的問(wèn)題。一服務(wù)器端
1.首先編寫(xiě)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程序,生成一些文件??梢园裺oapcpp2.exe拷貝到一add.h目錄下,用cmd執(zhí)行soapcpp2.exeadd.h就可以,在這個(gè)目錄下會(huì)自動(dòng)生成許多將來(lái)有用的文件,如add.namap,soapH.h,soapC.cpp,soapClient.cpp,soapServer.cpp等文件。soapcpp2.exe可以帶參數(shù)執(zhí)行,具體執(zhí)行soapcpp2.exe-h查看。3.新建一個(gè)win32控制臺(tái)工程,加入wsock32.lib庫(kù),將剛才生成的那些文件添加到工程中。然后編寫(xiě)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);//該句說(shuō)明該server的服務(wù)
soap_end(&add_soap);
}
}
return0;
}
//server端的實(shí)現(xiàn)函數(shù)與add.h中聲明的函數(shù)相同,但是多了一個(gè)當(dāng)前的soap連接的參數(shù)
intns__add(structsoap*add_soap,intnum1,intnum2,int*sum)
{
*sum=num1+num2;
return0;
}4.編譯這個(gè)程序,會(huì)提示錯(cuò)誤,將gsoap_win32目錄下stdsoap2.cpp,stdsoap2.h文件加入工程,重新編譯如果還有錯(cuò)誤,可能是你將add.h生成的文件添加入工程出錯(cuò)的原因。實(shí)際上在編寫(xiě)server程序時(shí),無(wú)須帶Client的那些文件,還有帶Lib的文件也無(wú)須添加到工程中。再重新編譯應(yīng)該就沒(méi)有問(wèn)題了,啟動(dòng)4567端口,在ie中輸入localhost:4567,如果顯示xml頁(yè)面,說(shuō)明程序已經(jīng)啟動(dòng)。二對(duì)應(yīng)的客戶端
1??蛻舳顺绦虼a如下:
#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);
//該函數(shù)是客戶端調(diào)用的主要函數(shù),后面幾個(gè)參數(shù)和add.h中聲明的一樣,前面多了3個(gè)參數(shù),函數(shù)名是接口函數(shù)名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.客戶端程序既可以新建一個(gè)新的win32控制臺(tái)程序,將剛才生成的nsmap,soapH.h,soapClient.h等文件加入工程,編譯既可。我是直接在原先工程中加入一客戶端代碼,將webserver.cpp文件移除,并且將soapServer.cpp等server端需要的文件移除,將soapClient.cpp等client端需要的cpp添加到工程,編譯既可。
3.啟動(dòng)server程序,F(xiàn)5客戶端程序,經(jīng)測(cè)試正常。三遇到的問(wèn)題
1.server端可以編譯成CGI方式執(zhí)行,而并不是綁定到某個(gè)端口,這種方式我沒(méi)有實(shí)踐。
if(argc<2)//noargs:assumethisisaCGIapplication
{
soap_serve(&soap);//serverequest,onethread,CGIstyle
soap_destroy(&soap);//deallocC++data
soap_end(&soap);//deallocdataandcleanup
}2.在編譯服務(wù)器及客戶端程序時(shí)一開(kāi)始對(duì)add.h生成的文件添加到工程,經(jīng)常出現(xiàn)問(wèn)題,需要自己不調(diào)試。特別是鏈接時(shí)段,server/client要與其生成的文件相對(duì)應(yīng),server調(diào)用生成的soapserver.cpp,client調(diào)用生成的soapclient.cpp文件。
3.多線程方式,在windows下建議用pthread_win32庫(kù),這里給出多線程下的例子。
一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);二多線程服務(wù)器關(guān)鍵代碼#include
#include
"calc.nsmap"
#include
"soapH.h"/**//////////////////////////////////////////////////////////////////////////
///宏與全局變量的定義
#define
BACKLOG(100)
#define
MAX_THR(10)
#define
MAX_QUEUE(1000)
pthread_mutex_tqueue_cs;
//隊(duì)列鎖
pthread_cond_t
queue_cv;
//條件變量
SOAP_SOCKET
queue[MAX_QUEUE];
//數(shù)組隊(duì)列
int
head=0,tail=0;
//隊(duì)列頭隊(duì)列尾初始化
/**///////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void*
process_queue(void*);
//線程入口函數(shù)
int
enqueue(SOAP_SOCKET);
//入隊(duì)列函數(shù)
SOAP_SOCKETdequeue(void);
//出隊(duì)列函數(shù)/**///////////////////////////////////////////////////////////////////////////
//線程入口函數(shù)
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;
}//入隊(duì)列操作
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;
}//出隊(duì)列操作
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;
}
/**///////////////////////////具體服務(wù)方法////////////////////////////////////////
//加法的實(shí)現(xiàn)
intns__add(structsoap*soap,doublea,doubleb,double*result)
{
*result=a+b;
returnSOAP_OK;
}
//減法的實(shí)現(xiàn)
intns__sub(structsoap*soap,doublea,doubleb,double*result)
{
*result=a-b;
returnSOAP_OK;
}
//乘法的實(shí)現(xiàn)
intns__mul(structsoap*soap,doublea,doubleb,double*result)
{
*result=a*b;
returnSOAP_OK;
}
//除法的實(shí)現(xiàn)
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;
}
//乘方的實(shí)現(xiàn)
intns__pow(structsoap*soap,doublea,doubleb,double*result)
{
*result=pow(a,b);
if(soap_errno==EDOM)/**//*soap_errno和errorno類(lèi)似,但是和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;
}/**///////////////////////////////////////////////////////////////////////////////////////////////////////
//主函數(shù)
intmain(intargc,char**argv)
{
structsoapServerSoap;
//初始話運(yùn)行時(shí)環(huán)境
soap_init(&ServerSoap);
//如果沒(méi)有參數(shù),當(dāng)作CGI程序處理
if(argc<2)
{
//CGI風(fēng)格服務(wù)請(qǐng)求,單線程
soap_serve(&ServerSoap);
//清除序列化的類(lèi)的實(shí)例
soap_destroy(&ServerSoap);
//清除序列化的數(shù)據(jù)
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);
//綁定服務(wù)端口
m=soap_bind(&ServerSoap,NULL,port,BACKLOG);
//循環(huán)直至服務(wù)套接字合法
while(!soap_valid_socket(m))
{
fprintf(stderr,"Bindporterror!");
m=soap_bind(&ServerSoap,NULL,port,BACKLOG);
}
fprintf(stderr,"socketconnectionsuccessful%d",m);
//生成服務(wù)線程
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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024土石方運(yùn)輸承包合同范本
- 2024園林綠化勞務(wù)合同
- 2024委托代理合同范文模板
- 2024學(xué)習(xí)借款合同和借據(jù)各自作用作文
- 國(guó)有企業(yè)業(yè)財(cái)融合存在的問(wèn)題與對(duì)策研究
- 課件背景圖片大全
- 年度機(jī)械設(shè)備電控產(chǎn)業(yè)分析報(bào)告
- 年度醫(yī)用材料及制品市場(chǎng)分析及競(jìng)爭(zhēng)策略分析報(bào)告
- 寫(xiě)人課件教學(xué)課件
- 6.3梯形的面積(基礎(chǔ)作業(yè))2024-2025學(xué)年五年級(jí)上冊(cè)數(shù)學(xué)人教版(含解析)
- 人教版2023-2024學(xué)年七年級(jí)數(shù)學(xué)上學(xué)期第一次月考測(cè)試卷
- SAP 成套銷(xiāo)售業(yè)務(wù)操作及配置詳解
- 高一第一次月考班會(huì)總結(jié)-82766課件
- 科普版小學(xué)英語(yǔ)六年級(jí)上冊(cè)全冊(cè)課件(附教案)-2
- 中班健康《身體上的洞洞》課件
- 幼兒園大班科學(xué)《奇妙的信》課件
- 角的度量(省一等獎(jiǎng))
- 中藥學(xué)專(zhuān)業(yè)自評(píng)報(bào)告
- 《富蘭克林效應(yīng)》讀書(shū)筆記
- 墻體-墻面裝修(建筑構(gòu)造)
- 淺談煤礦基層隊(duì)組的安全管理
評(píng)論
0/150
提交評(píng)論