gSoap開發(fā)webservice client實例及詳解_第1頁
gSoap開發(fā)webservice client實例及詳解_第2頁
gSoap開發(fā)webservice client實例及詳解_第3頁
gSoap開發(fā)webservice client實例及詳解_第4頁
gSoap開發(fā)webservice client實例及詳解_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

gSOAP是一個夸平臺的,用于開發(fā)WebService服務(wù)端和客戶端的工具,在Windows、Linux、MACOS和UNIX下使用C和C++語言編碼,集合了SSL功能。

下載地址:/projects/gsoap2官方網(wǎng)站:/Products/gsoap/index.html對于Windows平臺下開發(fā)客戶端,首先下載最新的gsoap_win32_2.7.6c.zip包,具體在以下地址:/sourceforge/gsoap2/gsoap_win32_2.7.6c.zip首先查看gsoap的User'sGuide,基本就能對gsoap有個全面的了解,通過閱讀Sample里的例子程序深入。然后搜索網(wǎng)上其它一些文章,比如:

gSOAP簡單多線程服務(wù)器程序/u1/55091/showart_430965.html

純cgSoap實現(xiàn)WebService

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

接下來我結(jié)合自己的實踐與理解,講講VC用gsoap下編寫webService和客戶端程序,有不對的地方還請大家指正,謝謝。

我以網(wǎng)上出現(xiàn)的實現(xiàn)一個簡單的加法函數(shù)為例,講講我在操作過程中遇到的問題。一服務(wù)器端

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程序,生成一些文件??梢园裺oapcpp2.exe拷貝到一add.h目錄下,用cmd執(zhí)行soapcpp2.exeadd.h就可以,在這個目錄下會自動生成許多將來有用的文件,如add.namap,soapH.h,soapC.cpp,soapClient.cpp,soapServer.cpp等文件。soapcpp2.exe可以帶參數(shù)執(zhí)行,具體執(zhí)行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的服務(wù)

soap_end(&add_soap);

}

}

return0;

}

//server端的實現(xiàn)函數(shù)與add.h中聲明的函數(shù)相同,但是多了一個當(dāng)前的soap連接的參數(shù)

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的文件也無須添加到工程中。再重新編譯應(yīng)該就沒有問題了,啟動4567端口,在ie中輸入localhost:4567,如果顯示xml頁面,說明程序已經(jīng)啟動。二對應(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ù),后面幾個參數(shù)和add.h中聲明的一樣,前面多了3個參數(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.客戶端程序既可以新建一個新的win32控制臺程序,將剛才生成的nsmap,soapH.h,soapClient.h等文件加入工程,編譯既可。我是直接在原先工程中加入一客戶端代碼,將webserver.cpp文件移除,并且將soapServer.cpp等server端需要的文件移除,將soapClient.cpp等client端需要的cpp添加到工程,編譯既可。

3.啟動server程序,F(xiàn)5客戶端程序,經(jīng)測試正常。三遇到的問題

1.server端可以編譯成CGI方式執(zhí)行,而并不是綁定到某個端口,這種方式我沒有實踐。

if(argc<2)//noargs:assumethisisaCGIapplication

{

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

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

soap_end(&soap);//deallocdataandcleanup

}2.在編譯服務(wù)器及客戶端程序時一開始對add.h生成的文件添加到工程,經(jīng)常出現(xiàn)問題,需要自己不調(diào)試。特別是鏈接時段,server/client要與其生成的文件相對應(yīng),server調(diào)用生成的soapserver.cpp,client調(diào)用生成的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);二多線程服務(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;

//隊列鎖

pthread_cond_t

queue_cv;

//條件變量

SOAP_SOCKET

queue[MAX_QUEUE];

//數(shù)組隊列

int

head=0,tail=0;

//隊列頭隊列尾初始化

/**///////////////////////////////////////////////////////////////////////////

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

void*

process_queue(void*);

//線程入口函數(shù)

int

enqueue(SOAP_SOCKET);

//入隊列函數(shù)

SOAP_SOCKETdequeue(void);

//出隊列函數(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;

}//入隊列操作

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;

}

/**///////////////////////////具體服務(wù)方法////////////////////////////////////////

//加法的實現(xiàn)

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

{

*result=a+b;

returnSOAP_OK;

}

//減法的實現(xiàn)

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

{

*result=a-b;

returnSOAP_OK;

}

//乘法的實現(xiàn)

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

{

*result=a*b;

returnSOAP_OK;

}

//除法的實現(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;

}

//乘方的實現(xiàn)

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;

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

//主函數(shù)

intmain(intargc,char**argv)

{

structsoapServerSoap;

//初始話運行時環(huán)境

soap_init(&ServerSoap);

//如果沒有參數(shù),當(dāng)作CGI程序處理

if(argc<2)

{

//CGI風(fēng)格服務(wù)請求,單線程

soap_serve(&ServerSoap);

//清除序列化的類的實例

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. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論