Article complet: SOAP with C/C++ & PHP

04.04.05

Permalink 04:49:43, Catégories: Australie, 1034 mots   French (FR)

SOAP with C/C++ & PHP

For my work, I need to create a client/server interface. The client must be programmed with C/C++ and the server with PHP.

After a quick look on the web, I found two projects of a SOAP C++ library which match with my requirement :
- Easysoap - http://easysoap.sourceforge.net/
- Axis - http://ws.apache.org/axis/index.html
- Gsoap - http://www.cs.fsu.edu/~engelen/soap.html

The main problem with the first one is the lake of maintenance of the project. Maybe there is no bug in it but the "last modification 12-April-2002" scared me a bit.
Despite the excellent reputation of apache's projects, I won't Axis because the requierement of having a webserver (apache) already installed on his computer (which is my case but not everybody).

For PHP, there is no standard version for PHP 4. There is one by default in PHP 5, but I am not ready to switch to this version (I know that I will have the envy to adapt my development with the object model that PHP 5 proposes).
One of the reference for PHP4 is :
- Nusoap - http://dietrich.ganx4.com/nusoap/index.php which has been developed using PHP (one file of 224 ko ...)

[Suite:]

The PHP server
It is quite simple.
Download the nusoap program.

Create a php file located on your webserver :

<?php
function encrypt($myString) {
    return md5("salt".md5($myString));
}

require('nusoap.php');

$server = new soap_server();

$server->configureWSDL('security', 'urn:secure'); // Name of the server & the namespace in order to create the wsdl doc

$server->register("encrypt", // method name
                array('symbol' => 'xsd:string'), // input parameters
                array('return' => 'xsd:string'), // output parameters
                'urn:secure', // namespace
                'urn:secure#encrypt'); // SOAP action

$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA)
                      ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

I declare the datatype of each variable to avoid mistake about datatypes.

The C client

/path/to/gsoap-linux-2.7/wsdl2h -c -o encrypt.h http://localhost/soap.php?wsdl

The -c option is used to force the generation in C.
This command creates the include thanks to the wsdl declaration.
In this file, we can find what we declared on the server (C++ style) :

int ns1__encrypt(
std::string symbol,
std::string &return_ // < response parameter
);

If you use C++, you will need the stlvector.h file in your current directory.

/path/to/gsoap-linux-2.7/soapcpp2 -c encrypt.h

Will generate the skeletons, xml sample of the flux ...

List of the files :

soapStub.h header file with data type annotations
soapH.h header file of soapC.cpp
soapC.c SOAP/XML (de)serializers for C/C++ data types
soapClient.c proxy stub routines for remote method calls
soapServer.c skeleton routines for service implementation
securityBinding.nsmap a namespace mapping table for the client application
securityBinding.encrypt.req.xml xml sample of the request
securityBinding.encrypt.res.xml xml sample of the response
encrypt.h the header file declarations
soapsecurityBindingObject.h Proxy class (ie C++) for the service
soapsecurityBindingProxy.h Proxy class (ie C++) for the client
soapClientLib.c
soapServerLib.c

Create a encryptclient.c file :

#include "soapH.h" // obtain the generated stub 
#include "securityBinding.nsmap" // obtain the namespace mapping table 
#include "stdio.h"

int main() { 
	struct soap soap; // gSOAP runtime environment 
	soap_init(&soap); // initialize runtime environment (only once) 
	char  *myVar="sandra";
	char *result;
	if (soap_call_ns1__encrypt(&soap, NULL, NULL, myVar , &result) == SOAP_OK) 
		printf("Key encrypted = %s ",result);
	else
		soap_print_fault(&soap, stderr); // display the SOAP fault message on the stderr stream 
	soap_end(&soap); // remove deserialized data and clean up
	soap_done(&soap); // detach the gSOAP environment 
	return (0);
}

To compile this wonderful application :
gcc -g -I/path/to/gsoap-linux-2.7 -Wall -o encryptclient encryptclient.c soapC.c soapClient.c /path/togsoap-linux-2.7/stdsoap2.c

The processus for a C++ application is almost the same except that you don't have to use the -c parameter when saopcpp2 and wsdl2h are called.
Generated files will have an other extension (cpp instead of c) and include an proxy (basically a wrapper to use the soap web service).

There is the C++ solution without the proxy :

#include "soapH.h" // obtain the generated stub
#include "securityBinding.nsmap" // obtain the namespace mapping table
#include <iostream>
#include <string>

using namespace std;
int main() {
        struct soap soap; // gSOAP runtime environment
        soap_init(&soap); // initialize runtime environment (only once)
        std::string myVar="sandra";
        std::string result;
        if (soap_call_ns1__encrypt(&soap, NULL, NULL, myVar , result) == SOAP_OK)
                cout << "Key encrypted = " << result;
        else
                soap_print_fault(&soap, stderr); // display the SOAP fault message on the stderr stream
        soap_destroy(&soap); // delete deserialized class instances (for C++ only)
        soap_end(&soap); // remove deserialized data and clean up
        soap_done(&soap); // detach the gSOAP environment
}

With the proxy (smaller & cleaner isn't it ?) :

#include "soapsecurityBindingProxy.h" /* get the gSOAP-generated proxy */
#include "securityBinding.nsmap" /* get service namespace bindings */
int main() { 
	securityBinding sec;
	string result; 
	if (sec.ns1__encrypt(string("sandra"), result) == SOAP_OK) 
		cout << "Key encrypted = " << result;  
	else
		soap_print_fault(sec.soap, stderr); 
}

For both sources, the compilation command is :

g++ -I/path/to/license/gsoap-linux-2.7 -Wall -o encryptclient encryptclient.cpp soapC.cpp soapClient.cpp /path/to/gsoap-linux-2.7/stdsoap2.cpp

If you want to use SSL (without prior authentication), just add this

if (soap_ssl_client_context(&soap,SOAP_SSL_NO_AUTHENTICATION,NULL,NULL,NULL,NULL,NULL)) {
	soap_print_fault(&soap, stderr);
	exit(1);
} 

and change the URL (https instead of http) in soapClient.{c/cpp]

URL = "https://localhost/soap.php";

And add :

-DWITH_OPENSSL -lssl -lcrypto

to gcc/g++.

Bonus - The client in Python with SOAPpy - http://pywebsvcs.sourceforge.net/ :

#!/usr/bin/python
import SOAPpy
try:
	server = SOAPpy.SOAPProxy("http://localhost:80/soap.php")
	print server.encrypt("sandra")
except Exception, e:
	print """Error : %s """% e

Sources :
Tutorial - Nusoap with PHP4 : http://codewalkers.com/tutorials/74/4.html
gSOAP User Guide : http://www.cs.fsu.edu/~engelen/soapdoc2.html
Creating a C/C++ client for a WebSphere Web service using WebSphere Studio Application Developer, gSOAP, and Dev-C++ : http://www-900.ibm.com/developerWorks/cn/wsdd/library/techarticles/0301_lin/lin_eng.shtml

Commentaires:

Commentaire de: BIGIRIMANA [Visiteur]
Salut,

Je m'applelle Olivier BIGIRIMANA,je suis burundais (BURUNDI)et j'ai 22ans.J'aime beaucoup l'AUSTRALIE et j'aimeriais des amies en AUSTRALIE.Ecrivez-moi s.v.p.
Permalien 16.05.05 @ 16:31
Commentaire de: LyonL [Visiteur]
moi c'est l'inverse le serveur doit etre en C pur. c'est pour un systeme embarqué. mais pour la compilation j'ai du mal je vais tenter une compil avec tes parametres.
Permalien 23.09.05 @ 11:10

Les commentaires sont fermés pour cet article.

A frog around the world

Mon séjour en Australie s'est terminé... Un an et demi de bonheur ! Cependant, ce blog continue. Je continue à garder le contact avec le pays et je continue à partager mes expériences.
Pour plus d'infos sur l'Australie, mon carnet de voyage est aussi disponible.
D'autres carnets de voyage sur Kikooboo !

Mars 2012
Lun Mar Mer Jeu Ven Sam Dim
<<  <   >  >>
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Catégories


Linkblog

Syndiquez ce blog XML

What is RSS?

powered by
b2evolution