wed services SOAP調用實例

此博文僅限於自己參考使用,描述不恰當之處請見諒


編寫頭文件:add.h

 在這裏我們不需要wsdl的文件,可以直接從.h文件來生成代碼其生成的.h並不能直接用,是被soapcpp2用來解釋生成soap框架代碼的。我們定義一個函數聲明文件,用來定義接口函數,名稱爲add.h

#ifndef _ADDH_
#define _ADDH_
int ns2_add(int num1,int num2,int *sum);
#endif

3、產生代碼框架

我們執行一下命令,自動生成一些遠程調用需要的文件。

拷貝 /home/qinyisong/gsoap_x386/bin/soapcpp2到所需文件夾

soapcpp2 -c add.h -I /home/qinyisong/gsoap_x386/share/gsoap/import/ -I /home/qinyisong/gsoap_x386/share/gsoap/custom/

-c是產生純C代碼,如果提示找不到typemap.dat,將gsoap/下的typemap.dat複製到當前目錄就可以了。通過上列命令我們會得到如下文件:       soapH.h        soapC.c          soap.nsmap      soapClient.c     soapServer.c     soapClientLib.c     soapServerLib.  soapStub.h



soapH.h  soap.c中函數及數據聲明,同時包含stdsoap.h頭文件,客戶端和服務器都會用到。

soapC.c  客戶端和服務器都會用到,soap通信協議的解析和編碼函數,使用soapH.h,其實核心文件。

soap.nsmap   xsi、xsd等命名空間

soapClient.c  客戶端使用, 有關於遠程調用服務器功能的函數實現

soapServer.c  服務器使用,有關於服務器被調用實現函數

  soapClientLib.c     soapServerLib  用來生成更上層的client和server的封裝庫,無用

soapStub.h  服務器和客戶端都用,根據用戶頭文件生成的soap通信協議數據結構定義以及soap操作服務和客戶端的函數。

 

 stdsoap2.h soap的基礎函數頭文件

stdsoap2.c soap的基礎函數比如soap初始化,soap的結構體堆分配以及各種設置函數等等


stdsoap2.c stdsoap2.h  必須拷貝到文件夾,不用生成,此文件實現soap的通信基礎函數和數據類型,是實現soap的底層網絡通信http等函數,與onvif.h無關

 先大概記住他們的名字,將來會提到他們。

4、添加服務端代碼,創建文件:addserver.c

#include "soapH.h"
#include "soap.nsmap"
int main(int argc,char **argv)
{
int m,s;
struct soap add_soap;
soap_init(&add_soap);
soap_set_namespaces(&add_soap,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);
soap_end(&add_soap);
}

}
return 0;
}

#if 1
int ns2_add(struct soap *add_soap,int num1,int num2,int *sum)

{
*sum=num1+num2;
return 0;

}

#endif

 

 

 

 

 

 


 

5、添加客戶端代碼,創建文件:addclient.c

#include "soapStub.h"
#include "soap.nsmap"
int add(const char *server,int num1,int num2,int *sum)
{
struct soap add_soap;
int result=0;
soap_init(&add_soap);
soap_set_namespaces(&add_soap,namespaces);
soap_call_ns2_add(&add_soap,server,NULL,num1,num2,sum);
printf("serveris%s,num1is%d,num2is%d/n",server,num1,num2);
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);
return result;

}

6、寫客戶端測試代碼,創建文件:client_test.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int add(const char *server,int num1,int num2,int *sum);
int main(int argc,char **argv)
{
int result=-1;
char server[128]={0};
int num1;
int num2;
int sum;
if(argc<4)
{
printf("usage:%s<ip:port>num1num2\n",argv[0]);
exit(1);
}
strcpy(server,argv[1]);
num1=atoi(argv[2]);
num2=atoi(argv[3]);
result=add(server,num1,num2,&sum);
if(result!=0)
{
printf("soaperror,errcode=%d\n",result);
}
else
{
printf("%d+%d=%d\n",num1,num2,sum);
}
return 0;

}

 

 

 

7、編寫Makefile,編譯前,先將gsoap-2.8\gsoap目錄下的stdsoap2.c和stdsoap2.h複製到當前目錄下,它提供了對SOAP協議的簡單調用。

GSOAP_ROOT = /home/qinyisong/gsoap_x386/share/gsoap
CC = gcc -g -DWITH_NONAMESPACES
INCLUDE = -I$(GSOAP_ROOT)
SERVER_OBJS = soapC.o stdsoap2.o soapServer.o addserver.o
CLIENT_OBJS = soapC.o stdsoap2.o soapClient.o addclient.o client_test.o
#make default
all:server
#make server
server:$(SERVER_OBJS) 
 $(CC) $(INCLUDE) -o addserver $(SERVER_OBJS)
 #make client
client:$(CLIENT_OBJS)
 $(CC) $(INCLUDE) -o client_test $(CLIENT_OBJS)
clean:
 rm -f *.o client_test

8、編譯服務端make server,編譯客戶端make client 得到addserver和client_test

9、測試



一個最簡單的soap調用的例子完成了。

實例分析

服務端代碼

下面我們來分析上面的例子,剛纔我們只是創建一個add.h頭文件,在add.h頭文件中聲明瞭一個函數:

  1. int ns2__add( int num1, int num2, int* sum );  
其他所有的的代碼都是一句他來生成的。那麼這個的實體在哪?對,就是在需要我們自己添加的addserver.c中:


但是它好像多了一個struct soap類型的參數,這是soap全局運行環境,所有的函數都第一個包含這個參數。注意上面的Makefile,不管是編譯server還是編譯client都是沒有用到剛纔的add.h文件的。ns2__add真正的聲明在自動產生的soapStub.h中


然後在自動產生的soapServer.c中被soap_serve_ns2__add()函數調用。這樣,就將真正的加法運算的ns2__add函數和soap代碼框架聯繫了起來。那麼,在客戶端的代碼中又是怎樣來調用這個遠程函數的呢?

客戶端代碼

在剛纔添加的addtest.c中main函數中調用一個簡單的add函數


這個函數的實現也是我們自己添加的,在addclient.c中:


這個函數有些複雜,因爲它把客戶端的調用和soap聯繫了起來,還記得嗎,我們編譯server和client的時候複製了兩個文件stdsoap2.h和stdsoap2.c,這裏面的soap_init() soap_end()等函數來自他們。stdsoap2提供了soap協議的簡單操作,之需要簡單的函數調用就能完成遠程的函數調用。注意soap_call_ns2__add(),它同樣在soapStub.h中聲明,只不過是Client-Side Call Stubs,不明白stub意思的可以搜索rpc


這個函數的實現在自動產生的soapClient.c源文件中。同樣不需要我們實現。

這樣就可以通過調用gSOAP提供的stdsoap2的soap_init和自動產生的soap_call_ns2__add就實現了遠程主機上的ns2__add函數的調用



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章