wed services SOAP调用实例

来源:互联网 发布:拖欠淘宝贷款3个月 编辑:程序博客网 时间:2024/05/12 16:54

此博文仅限于自己参考使用,描述不恰当之处请见谅


编写头文件: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头文件中声明了一个函数:

[cpp] view plaincopy
  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函数的调用



0 0