c++ webservices搭建

一、准备工具

      安装gsoap

二、gsoap使用

1. soapcpp2使用参数如下(soapcpp2是将.h文件解析生成.wsdl c/c++文件,工客户端服务端使用):

-1      使用SOAP 1.1进行编译
-2      使用SOAP 1.1进行编译
-C      只生成客户端代码
-S      只生成服务端代码
-T      generate server autorem -test code
-L      不生成soapClientLib/soapServerLib文件(使用-i就有-L的功能,理解为将ClientLib和Client变对象)
-a      use SOAPAction HTTP/WSA header to invoke serverrem -side operations
-b      serialize byte arrays char[N] as string
-c      生成c源代码(没有现象) generate C source code
-dpath  生成代码路径
-e      generate SOAP RPC encoding style bindings
-fN     file split of N XML serializer implementations per file (N>=10)
-h      display help info
-Ipath  代码导入路径
-i      从SOAP结构继承,生成C++服务代理和对象
-j      通过共享SOAP结构,生成C++服务代理和对象
-k      generate data structure walkers (experimental)
-l      generate linkable modules (experimental)
-m      generate Matlab(tm) code for MEX compiler
-n      use service name to rename service functions and namespace table
-pname  使用新前缀"name"代替"soap"       save files with new prefix name instead of 'soap'
-qname  在所有声明中使用命名空间"name"(同时拥有-p功能)
-s      生成具有严格的XML验证检查反序列化代码 generate deserialization code with strict XML validation checks
-t      生成代码全部使用xsi:type类型soap/XML消息。 generate code for fully xsi:type typed SOAP/XML messaging
-u      uncomment comments in WSDL/schema output by suppressing XML comments
-v      显示版本信息(没有看到现象--生成代码没有变化)
-w      不生成WSDL和模式文件
-x      不生成XML文件
-y      包括C / C++类型访问信息的示例XML消息(没有看到现象)
 

2.wsdl常使用的参数(wsdl是解析.wsdl文件生成c/c++代码及.h文件)

  -o filename.h   将wsdl转化为filename.h头文件。

  -s         不生成STL代码

  -c         生成纯C风格的头文件,这将去除C++的一些特性

  -n  name      使用name代替默认前缀ns

  -t filename.dat  使用filename.dat代替默认的typemap.dat文件

  -zX        兼容之前的X版本

3.例子

编写如下.h文件

//gsoap ns1 service name: control             
//gsoap ns1 service namespace: http://192.168.14.152:8888/control.wsdl
//gsoap ns1 service location: http://localhost:8888
//gsoap ns1 service executable: add.cgi
//gsoap n1s service encoding: encoded
//gsoap ns1 schema namespace: urn:control

int ns1__add(int num1,int num2,int* sum);
int ns1__div(int num1,int num2,int* result);

需注意:

(头文件第一行定义服务名称,在生成的文件中有些会以它命名;

第二行定义namespace;第三行定义客户端访问服务端地址(如果没有指定给客户端服务地址);

第四行在xml文件中体现,也是地址;第五行定义服务编码,需要soapcpp2 -e有用

第六行由于服务器接口命名空间为control,因此urn:后面必须为control

这些信息全在生成的.wsdl文件里显示

)

1、add.h文件前面的几句注释不能删除,为soapcpp2需要识别的标志;

2、接口函数的返回值只能是int,是soap调用的结果,一般通过soap.error来判断soap的连接情况,这个返回值没有用到;

3、接口函数的最后一个参数为传出参数,如果需要传出多个参数,需要自己定义一个结构将返回项封装;  

4、在.h文件中不能include别的.h文件,可能不能生效,需要用到某些结构的时候需要在该文件中直接声明;

5、如果客户端的调用不需要返回值,那么最后一个参数为空;

另外,gSoap对“”和“_”(下划线、双下划线)有特殊用法,接口定义时函数名前要加上命名空间名和双下划线 
举例:加法运算 
int add(int num1, int num2, int &num3); 
在接口头文件定义时要写成如下格式 
int ns1__add(int num1, int nmu2, int &num3); 
其中 
“ns1”是命名空间名称,此名称可以自定义成其它名字 但其后”urn:control”不可随意更改,这个是要与服务端统一的 
“__”是编译时识别符号,如果没有的话xml文件是编译不出来的

“_”(单下划线)定义名称中要慎用,自己定义的变量或函数名称中使用下划线的地方要在下划线后加上”USCORE”; 
例 定义 ns1__add_sum(int num_1, int num2, int &num_3); 
要写成如下形式 
ns1__add_USCOREsum(int num_USCORE1, int num2, int &num_USCORE3); 
“add”是接口函数名 这个是客户端与服务器统一的接口名字 

这里ns1命名空间是由//gsoap ns1来的,如果写成//gsoap ns 那么函数前面命名空间为ns,如果函数前面命名空间为其他名,则生成wsdl时,使用默认的配置,不是.h头文件里配置的信息了

服务端代码(addserver.cpp):

#include "mixService.h"
#include "mix.nsmap"
#include
#include
int Service::add(int num,int num2,int* sum)
{
    *sum=num+num2;
    printf("sleep...\n");
    sleep(5);
    return 0;
}
int Service::div(int num1,int num2,int* result)
{

    *result=9;
    return 0;
}

int http_get(soap* soap)
{
    FILE*fd = NULL;
    printf("http_get\n");
    char* s = strchr(soap->path,'?');
    printf("soap->path: %s\n",soap->path);
/*    if(!s || strcmp(s,"?wsdl"))
    {
        printf("?wsdl\n");
        return SOAP_GET_METHOD;
    }
*/
    fd=fopen("./add.wsdl","rb");
    if(fd==NULL)
    {
        return 404;
    }
    soap->http_content="text/xml";
    soap_response(soap,SOAP_FILE);
    for(;;)
    {
        size_t r = fread(soap->tmpbuf,1,sizeof(soap->tmpbuf),fd);
        if(!r)
        {
            printf("finish wsdl\n");
            break;
        }
        if(soap_send_raw(soap,soap->tmpbuf,r))
        {
            printf("fault transport\n");
            break;
        }
    }
    fclose(fd);
    soap_end_send(soap);
    return SOAP_OK;

}

int main(int argc,char**argv)
{
    Service m_sev;
    m_sev.fget=http_get;//发布webservice,将wsdl文件发出
    if(argc<2)
    {
        printf("input num less\n");
        return 0;
    }
    else
    {
        int n = m_sev.bind("192.168.14.194",atoi(argv[1]),1);
        //printf("n: %d\n",n);    
        //int m = m_sev.bind(NULL,atoi(argv[1]),1);
        //printf("m: %d\n",m);
        if(n<0)
        {
            m_sev.soap_print_fault(stderr);
            return 0;
        }
        for(;;)
        {
        //    int r = m_sev.accept();
        //    fprintf(stderr,"socket connection successful:socket = %d\n",r);
            printf("execute run\n");
            m_sev.run(atoi(argv[1]));
            printf("execute finished\n");
            soap_end(&m_sev);
        }
    }

}
客户端代码(addclient.cpp)

#include "mixProxy.h"
#include "mix.nsmap"

int main()
{
    int a=0,b=19,sum=0;
    int c=2,g=5,s=0;
    Proxy addp;

    addp.soap_endpoint = "192.168.14.194:8888";
    printf("endpoint: %s\n",addp.soap_endpoint);
    addp.add("192.168.14.194:8888",NULL,a,b,&sum);
    printf("sum: %d\n",sum);
    addp.add(c,g,&s);
    printf("s: %d\n",s);

    return 0;
}
makefile文件如下:供参考

GSOAP_ROOT=/usr/local/gsoap/
GSOAP_BIN=$(GSOAP_ROOT)bin
GSOAP_I=$(GSOAP_ROOT)include
WSNAME=mix
CC=g++ -g -DWITH_NONAMESPACES
INCLUDE=-I $(GSOAP_I)
SERVER_OBJS=$(WSNAME)C.o $(WSNAME)Service.o stdsoap2.o addserver.o
CLIENT_OBJS=$(WSNAME)C.o $(WSNAME)Proxy.o stdsoap2.o addclient.o
ALL_OBJS=$(WSNAME)C.o $(WSNAME)Service.o ${WSNAME}Proxy.o addserver.o addclient.o
all:server client

${WSNAME}.wsdl:${WSNAME}.h
    $(GSOAP_BIN)/soapcpp2 -p$(WSNAME) -x -i -n ${WSNAME}.h
stdsoap2.o:$(GSOAP_I)/stdsoap2.cpp
    $(CC) -c $?
$(ALL_OBJS):%.o:%.cpp
    $(CC) -c $? $(INCLUDE)
server:Makefile ${WSNAME}.wsdl  $(SERVER_OBJS)
    $(CC) -o ${WSNAME}server $(SERVER_OBJS) $(INCLUDE)
client:Makefile ${WSNAME}.wsdl $(CLIENT_OBJS)
    $(CC) -o ${WSNAME}client $(CLIENT_OBJS) $(INCLUDE)

clean:
    rm -f *.o *.xml *.a *.wsdl *.nsmap $(WSNAME)H.h $(WSNAME)C.cpp \
    $(WSNAME)Service.cpp $(WSNAME)Proxy.cpp $(WSNAME)Stub.* $(WSNAME)$(WSNAME)Proxy.* \
    $(WSNAME)$(WSNAME)Object.* $(WSNAME)ServerLib.c $(WSNAME)ClientLib.c \
    $(WSNAME)server $(WSNAME)client *.xsd $(WSNAME)Service.h $(WSNAME)Proxy.h
 

你可能感兴趣的:(c++)