SOAP current time client & server example
=========================================
Overview
--------
This example implements a simple SOAP/XML API client and server in C++ to obtain the current time. The Web service specified is a tiny one-liner. The client and server programs are tiny too.
A more interesting one-liner example service is our [gSOAP Docker container example](../docker/index.html) that does not require a Web server installed as it runs an image of a stand-alone service within a container.
[![To top](../../images/go-up.png) To top](#)
Web services specification example
----------------------------------
The XML Web service is specified in the [`gmt.h`](gmt.h) file for the gSOAP soapcpp2 tool to process. This [`gmt.h`](gmt.h) specification defines one operation in just one line of code to return the current time in GMT:
t__gmt(time_t*);
[![To top](../../images/go-up.png) To top](#)
Implementing the client application
-----------------------------------
The client application [`gmtclient.cpp`](gmtclient.cpp) is run at the command line and prints the current time:
#include "soapH.h"
#include "gmt.nsmap"
int main()
{
time_t t;
struct soap *soap = soap_new();
soap_call_t__gmt(soap, "http://localhost:8080", "", &t);
printf("The current time is %s\n", ctime(&t));
soap_destroy(soap);
soap_end(soap);
soap_free(soap);
return 0;
}
See the [tutorials](https://www.genivia.com/tutorials.html) on how to use HTTP proxies and HTTPS.
[![To top](../../images/go-up.png) To top](#)
Build steps for the client application
--------------------------------------
Generate the service and data binding interface for the client side with:
[command]
soapcpp2 -r -CL gmt.h
where option `-r` generates a report, and option `-CL` generates the client side only without (the unused) lib files.
This generates several files, including:
* [`soapStub.h`](soapStub.h) a copy of the specification in plain C/C++ header file syntax without annotations.
* [`soapH.h`](soapH.h) declares XML serializers.
* [`soapC.cpp`](soapC.cpp) implements XML serializers.
* [`soapClient.cpp`](soapClient.cpp) implements the client-side XML services API.
* [`gmt.nsmap`](gmt.nsmap) XML namespace binding table to #include
* [`soapReadme.md`](soapReadme.html) service and data binding interface details.
To build the example client application we also need `stdsoap2.h` and `stdsoap2.cpp`:
[command]
c++ -o gmtclient gmtclient.cpp stdsoap2.c soapC.cpp soapClient.cpp
[![To top](../../images/go-up.png) To top](#)
Implementing a CGI server application
-------------------------------------
The CGI server application [`gmtserver.cpp`](gmtserver.cpp) implements the service operations and accepts requests on stdin using `soap_serve(soap)`:
#include "soapH.h"
#include "gmt.nsmap"
int main()
{
return soap_serve(soap_new());
}
int t__gmt(struct soap *soap, time_t *t)
{
*t = time(0);
return SOAP_OK;
}
Install the CGI application in the cgi-bin folder of your Web server.
To implement stand-alone services running as a Web server without requiring a third-party Web server such as Apache, see the [calc++ example](../calc/index.html) for an example. See also our [tutorials](https://www.genivia.com/tutorials.html) for details on deploying services with Apache or IIS and how to increase the robustness of services.
[![To top](../../images/go-up.png) To top](#)
Implementing a stand-alone server application
---------------------------------------------
The stand-alone local server application [`gmtserver_local.cpp`](gmtserver_local.cpp) implements the service operations and accepts requests on port 8080.
#include "soapH.h"
#include "gmt.nsmap"
int main()
{
struct soap *soap = soap_new();
SOAP_SOCKET m = soap_bind(soap, NULL, 8080, 1);
if (soap_valid_socket(m)) == SOAP_OK
{
fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
while (true)
{
SOAP_SOCKET s = soap_accept(soap);
fprintf(stderr, "Socket connection successful: socket = %d\n", s);
if (soap_valid_socket(s) != SOAP_OK)
break;
soap_serve(soap);
soap_destroy(soap);
soap_end(soap);
}
}
soap_print_fault(soap, stderr);
soap_free(soap);
exit(1);
}
int t__gmt(struct soap *soap, time_t *t)
{
*t = time(0);
return SOAP_OK;
}
[![To top](../../images/go-up.png) To top](#)
Build steps for the server application
--------------------------------------
Generate the service and data binding interface for the server side with:
[command]
soapcpp2 -r -SL gmt.h
where option `-r` generates a report, and option `-SL` generates the server side only without (the unused) lib files.
This generates several files, including:
* [`soapStub.h`](soapStub.h) a copy of the specification in plain C/C++ header file syntax without annotations.
* [`soapH.h`](soapH.h) declares XML serializers.
* [`soapC.cpp`](soapC.cpp) implements XML serializers.
* [`soapServer.cpp`](soapServer.cpp) implements the server-side XML services API.
* [`gmt.nsmap`](gmt.nsmap) XML namespace binding table to #include
* [`soapReadme.md`](soapReadme.html) service and data binding interface details.
To build the example server application we also need `stdsoap2.h` and `stdsoap2.cpp`:
[command]
c++ -o gmtserver gmtserver.cpp stdsoap2.cpp soapC.cpp soapServer.cpp
c++ -o gmtserver_local gmtserver_local.cpp stdsoap2.cpp soapC.cpp soapServer.cpp
[![To top](../../images/go-up.png) To top](#)
Running the example
-------------------
[command]
./gmtserver_local &
./gmtclient
The current time is Sun Jun 4 15:43:22 2017
[![To top](../../images/go-up.png) To top](#)
Readme report
-------------
See the auto-generated [soapReadme](soapReadme.html) for this example.
[![To top](../../images/go-up.png) To top](#)