[gSOAP] gSOAP generates service proxy and Object C language code example

Keywords: xml Makefile calculator encoding

gSOAP is used to implement a simple server and proxy for four operations.

Table of Contents

Header file

Write the header file calc.h

Generate header file calc.h

How to use wsdl2h

Generate server and client (agent) programs

How to use soapcpp2

Complete makefile

Client & server code

Server code calcServer.cc

Client code calcClient.cc

Function

Whole process

Try to use gSOAP to realize a simple server code of four operations, and give

Header file

Write the header file calc.h

//gsoap ns service name: calc Simple calculator service 
//gsoap ns service style: rpc //gsoap ns service encoding: encoded 
//gsoap ns service namespace: http://localhost/calc.wsdl 
//gsoap ns service location: http://localhost/server.cgi 
//gsoap ns schema namespace: urn:calc 


//gsoap ns service method: add Sums two values
int ns__add(double a, double b, double *result);

//gsoap ns service method: sub Subtracts two values
int ns__sub(double a, double b, double *result);

//gsoap ns service method: mul Multiplies two values
int ns__mul(double a, double b, double *result);

//gsoap ns service method: div Divides two values
int ns__div(double a, double b, double *result);

//gsoap ns service method: pow Raises a to b
int ns__pow(double a, double b, double *result);

Note that "\\\\\" in NS add is double underlined.

Generate header file calc.h

You can also generate a header file through the wsdl 2H instruction by using a wsdl file, as follows:

How to use wsdl2h

wsdl 2H is used as the conversion of wsdl and. H files. soapcpp2 uses header files to generate h and cpp files needed for client / server development.
Some frequently used instructions are as follows:
- o filename.h converts the wsdl to a filename.h header file.
- s does not generate STL code
 - C generates pure C-style header files, which will remove some features of C + +
- N name use name instead of the default prefix ns
 - t filename.dat use filename.dat instead of the default typemap.dat file
 - zX compatible with previous versions of X

Generate server and client (agent) programs

Then the corresponding soap proxy code is generated by using the soapcpp2 instruction. The common options and usage of soapcpp2 are as follows:

How to use soapcpp2

wsdl 2H is used as the conversion of wsdl and. H files. soapcpp2 uses header files to generate h and cpp files needed for client / server development.
Some frequently used instructions are as follows:
- i generates the proxy and object of the server, which are inherited from the soap struct.
- j is similar to - i, except that the generated proxy class does not inherit from soap struct, but contains a pointer containing a soap structure. Agent classes that live in this way are easy to communicate with each other
 - C generate client code only
 - S only generates server code
 - x does not generate an xml file. Without this, a descriptive xml file will be generated for each operation defined in the header file
 - L does not generate soapClientLib and soapServerLib files
 - p name changes the filename prefix instead of soap
 - q name specifies the namespace name used by proxy classes and objects, including the filename prefix

Can be passed separately

soapcpp2 -S -i calc.h

and

soapcpp2 -C -i calc.h

Generate the server and client (agent) programs soapcalcService.cpp, soapcalcProxy.cpp.

Complete makefile

HDR_CALC:=calc.h
SRC_SERVER:=calcServer.cc
SRC_CLIENT:=calcClient.cc


SOAP_SRV:=soapC.cpp soapcalcService.cpp
SOAP_CLT:=soapC.cpp soapcalcProxy.cpp

LIBS:=-lgsoap++

all: server client

#-i: generate C + + service agents and objects inherited from soap structure.
${SOAP_SRV}:${HDR_CALC}
	soapcpp2 -S -i ${HDR_CALC}
	
${SOAP_CLT}:${HDR_CALC}
	soapcpp2 -C -i ${HDR_CALC}


client:${HDR_CALC} ${SOAP_CLT}
	g++ -o client ${SRC_CLIENT} ${SOAP_CLT} ${LIBS}

server:${HDR_CALC} ${SOAP_SRV}
	g++ -o server ${SRC_SERVER} ${SOAP_SRV} ${LIBS}


clean:
	rm -rf client server *.xml *.nsmap soap*

Client & server code

Server code calcServer.cc

#include "soapcalcService.h"
#include "calc.nsmap"

int main(int argc, char **argv)
{ 
    calcService calc;

    if(argc < 2)
    {
        fprintf(stderr, "Usage: calcserver++ <port>\n");
        exit(0);
    }

    if (argc < 2)
        calc.serve();   /* serve as CGI application */
    else
    { 
        int port = atoi(argv[1]);
        if (!port)
        { 
            fprintf(stderr, "Usage: calcserver++ <port>\n");
            exit(0);
        }
        /* run iterative server on port until fatal error */
        if (calc.run(port))
        { 
            calc.soap_stream_fault(std::cerr);
            exit(-1);
        }
    }
    return 0;
} 

int calcService::add(double a, double b, double *result)
{ 
    *result = a + b;
    return SOAP_OK;
} 

int calcService::sub(double a, double b, double *result)
{ 
    *result = a - b;
    return SOAP_OK;
} 

int calcService::mul(double a, double b, double *result)
{ 
    *result = a * b;
    return SOAP_OK;
} 

int calcService::div(double a, double b, double *result)
{ 
    if (b)
        *result = a / b;
    else
    { 
        char *s = (char*)soap_malloc(this, 1024);
        //    (SOAP_SNPRINTF(s, 1024, 100), "<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b);
        snprintf(s, 1024, "<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b);
        return soap_senderfault("Division by zero", s);
    }
    return SOAP_OK;
} 

int calcService::pow(double a, double b, double *result)
{ 
    *result = ::pow(a, b);
    if (soap_errno == EDOM)   /* soap_errno is like errno, but compatible with Win32 */
    { 
        char *s = (char*)soap_malloc(this, 1024);
        //    (SOAP_SNPRINTF(s, 1024, 100), "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b);
        snprintf(s, 1024, "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b);
        return soap_senderfault("Power function domain error", s);
    }
    return SOAP_OK;
}

Client code calcClient.cc

#include "soapcalcProxy.h"
#include "calc.nsmap"

char server[256] = "http://127.0.0.1:";

int main(int argc, char **argv)
{ 
    if (argc < 5)
    { 
        fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num port\n");
        exit(0);
    }
    
    double a, b, result;
    a = strtod(argv[2], NULL);
    b = strtod(argv[3], NULL);

    calcProxy calc;
    strcat(server, argv[4]);
    calc.soap_endpoint = server;
    
    switch (*argv[1])
    { 
        case 'a':
            calc.add(a, b, &result);
            break;
        case 's':
            calc.sub(a, b, &result);
            break;
        case 'm':
            calc.mul(a, b, &result);
            break;
        case 'd':
            calc.div(a, b, &result);
            break;
        case 'p':
            calc.pow(a, b, &result);
            break;
        default:
            fprintf(stderr, "Unknown command\n");
            exit(0);
    }
    
    if (calc.error)
        calc.soap_stream_fault(std::cerr);
    else
        printf("result = %g\n", result);
    
    return 0;
}

Function

One terminal:
$ ./server 121212

Another terminal:
$ ./client add 123 234 121212
result = 357

Whole process

 

575 original articles published, 279 praised, 490000 visitors+
His message board follow

Posted by wangsc66 on Tue, 11 Feb 2020 06:21:00 -0800