Interim Notes:
| command | notes |
|---|---|
| yum list http\* | see what is available |
| sudo yum install httpd-tools | you might already have this |
| sudo yum install httpd-devel | includes development headers as well as apxs |
Note: on CentOS-8 or Rocky-8 you might wish to replace 'yum' with 'dnf'
// =================================================================== // title : calcclient_102.c (copied from gsoap ver 2.8.117) // source : https://www.genivia.com/examples/calc/index.html // purpose : Example calculator client in C // changes : Neil Rieck (Waterloo, Ontario, Canada) // platform: CentOS-7 or Rocky-8 // prepare : // 1) yum install gsoap\* # CentOS-7 // dnf install gsoap\* # Rocky-8 // build : // 1) soapcpp2 -c -x calc.h # generate wsdl from calc.h // 2) gcc -o calcclient calcclient_102.c soapC.c soapClient.c -lgsoap // 3) gcc -o calcserver calcserver_101.c soapC.c soapServer.c -lgsoap -lm // test-1 : // 1) ./calcserver 5001 // 2) ./calcclient add 123 456 // notes : // 1) I installed gsoap-2.8.16 via 'yum' // 2) Many of the new demos are targeted to a higher version // 3) Some tweaks are needed for use with gcc on Linux (CentOS-7) // 4) connecting to calcserve2 is done by cgi-bin
// 5) connecting to calcserve3 is done by the mod_gsoap plugin // history : // 20211207 NSR copied source code here // 20211207 NSR modified for use with CentOS-7 (see aaa_help.txt) // 20230216 NSR updated for start of next phase project // =================================================================== #include "soapH.h" #include "calc.nsmap" char *url[] = { // array of string pointers "http://websrv.cs.fsu.edu/~engelen/calcserver.cgi", "http://localhost:5001", "http://kawc4n.on.bell.ca/cgi-bin/calcserver2", "http://kawc4n.on.bell.ca/calcserver3"}; char server[255]; char buffer[255]; int choice; int i; int menusize; // // the big kahoona // int main(int argc, char **argv) { struct soap soap; double a, b, result; if (argc < 4){ fprintf(stderr, "Usage: %s [add|sub|mul|div|pow] num num\n", argv[0]); exit(0); } printf("Program: %s\n", argv[0]); printf("Destination Menu:\n"); menusize = sizeof(url) / sizeof(url[0]); for(i=0;i<menusize;i++){ printf(" %ld %s\n",i+1, url[i]); } printf(" 1024-5999 for any local port\n"); printf("choice? "); fgets(buffer, sizeof (buffer), stdin); for (i=0; sizeof (buffer); i++){ if (buffer[i] == '\n'){ buffer[i] = '\0'; break; } } choice = strtol(buffer, NULL, 10); if ((choice > 0) && (choice <= menusize)){ sprintf(server,"%s", url[choice-1]); } else if ((choice >=1024) && (choice <=5999)){ sprintf(server,"%s%s","http://localhost:",buffer); } else { printf("-e-bad choice\n"); exit(1); } printf("%s\n",server); // // original code continues // soap_init1(&soap, SOAP_XML_INDENT); a = strtod(argv[2], NULL); b = strtod(argv[3], NULL); switch (*argv[1]) { case 'a': soap_call_ns__add(&soap, server, "", a, b, &result); break; case 's': soap_call_ns__sub(&soap, server, "", a, b, &result); break; case 'm': soap_call_ns__mul(&soap, server, "", a, b, &result); break; case 'd': soap_call_ns__div(&soap, server, "", a, b, &result); break; case 'p': soap_call_ns__pow(&soap, server, "", a, b, &result); break; default: fprintf(stderr, "Unknown command\n"); exit(0); } if (soap.error) soap_print_fault(&soap, stderr); else printf("result = %g\n", result); soap_destroy(&soap); soap_end(&soap); soap_done(&soap); return 0; }
caveat: the official docs say to replace "main()" with "IMPLEMENT_GSOAP_SERVER()" which did not work for me. A little hack with the "nm" proved that I needed both of them when building recipe-3
//========================================================================
// file : calcserver_101.c
// notes:
// 1) Started by copying calcserver_100.c then added compiler directives
// Normally you would only publish one program but I did not want to
// complicate a simple demo written with pedagogical intent)
// 2) Find additional notes in file 'calcserver_100.c' (this folder)
// build: CentOS-7.7 via gcc:
// 0) build wsdl etc (for all three recipes)
// soapcpp2 -c -x calc.h
// 1) compile server (standalone)
// gcc calcserver_101.c soapC.c soapServer.c \
// -o calcserver \
// -lgsoap -lm -DRECIPE=1
// 2) compile server (for Apache via cgi-bin)
// gcc calcserver_101.c soapC.c soapServer.c \
// -o calcserver2 \
// -lgsoap -lm -DRECIPE=2
// 3) compile server (for Apache via mod_gsoap)
// # a hack to force the installed file to be calcserver3
// cp calcserver_101.c calcserver3.c # my hack
// soapcpp2 -c -x calc.h # make files
// sudo apxs -i -n calcserver3 -c -DRECIPE=3 \
// -I/home/neil/gsoap/apache/mod_gsoap-0.6/apache_20 \
// calcserver3.c soapC.c soapServer.c \
// -lgsoap -lm
//========================================================================
#include "soapH.h"
#include "calc.nsmap"
// macro: RECIPE
// value: 1: default (interactive)
// 2: for Apache cgi-bin
// 3: for Apache plugin 'mod_gsoap'
#ifndef RECIPE
# define RECIPE 1
#endif
//-----------------------------------------------------------
// NSR change
// 1) copied the following block from file stdsoap2.h of gsoap version 2.8.117
// 2) alternatively, replace all 'SOAP_SNPRINTF' code with something like this:
// { char *s = (char*)soap_malloc(soap, 1024);
// sprintf(s, "<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b);
// return soap_sender_fault(soap, "Division by zero", s); }
//-----------------------------------------------------------
# ifdef HAVE_SNPRINTF
# if _MSC_VER >= 1400
# define SOAP_SNPRINTF(buf, len, num) void)_snprintf_s((buf), (len), _TRUNCATE
# define SOAP_SNPRINTF_SAFE(buf, len) void)_snprintf_s((buf), (len), _TRUNCATE
# else
# define SOAP_SNPRINTF(buf, len, num) void)snprintf((buf), (len)
# define SOAP_SNPRINTF_SAFE(buf, len) void)snprintf((buf), (len)
# endif
# else
# define SOAP_SNPRINTF(buf, len, num) (len) <= (num)) ? (void)((buf)[0] = '\0') : (void)sprintf((buf)
# define SOAP_SNPRINTF_SAFE(buf, len) void)sprintf((buf)
# endif
//--------------------------------------------------------
#if (RECIPE==1)
//
// original code resumes (mostly an interactive demo)
// notes:
// 1) if you start with an argument it will listen on that port (eg. 5001)
// 2) the CGI part of this demo works with mod_gsoap via apache-1.3
// but not mod_gsoap via apache-2.4 (read on)
//
int main(int argc, char **argv) {
SOAP_SOCKET m, s; /* sockets */
struct soap soap;
soap_init(&soap);
if (argc < 2) {
soap_serve(&soap); /* serve as CGI application */
}
else
{
m = soap_bind(&soap, NULL, atoi(argv[1]), 1);
if (!soap_valid_socket(m)) {
soap_print_fault(&soap, stderr);
exit(1);
}
fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
for ( ; ; )
{
s = soap_accept(&soap);
fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);
if (!soap_valid_socket(s))
{
soap_print_fault(&soap, stderr);
exit(1);
}
soap_serve(&soap);
soap_end(&soap);
}
}
return 0;
}
#endif
//-------------------------------------------------------------------
// RECIPE 2 (for Apache cgi-bin)
//
#if ((RECIPE==2)||(RECIPE==3))
int main() {
return soap_serve(soap_new());
}
#endif
//-------------------------------------------------------------------
// RECIPE 3 (for use with Apache plugin: mod_gsoap)
//
#if (RECIPE==3)
#include "apache_gsoap.h"
IMPLEMENT_GSOAP_SERVER()
#endif
//-------------------------------------------------------------------
// common code for all recipes
//-------------------------------------------------------------------
int ns__add(struct soap *soap, double a, double b, double *result)
{
(void)soap;
*result = a + b;
return SOAP_OK;
}
int ns__sub(struct soap *soap, double a, double b, double *result)
{
(void)soap;
*result = a - b;
return SOAP_OK;
}
int ns__mul(struct soap *soap, double a, double b, double *result)
{
(void)soap;
*result = a * b;
return SOAP_OK;
}
int ns__div(struct soap *soap, double a, double b, double *result)
{
if (b)
*result = a / b;
else
{
char *s = (char*)soap_malloc(soap, 1024);
(SOAP_SNPRINTF(s, 1024, 100),
"<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b);
return soap_sender_fault(soap, "Division by zero", s);
}
return SOAP_OK;
}
int ns__pow(struct soap *soap, 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(soap, 1024);
(SOAP_SNPRINTF(s, 1024, 100),
"<error xmlns=\"http://tempuri.org/\">Can't raise %f to %f</error>", a, b);
return soap_sender_fault(soap, "Power function domain error", s);
}
return SOAP_OK;
}
//-------------------------------------------------------------------
Back to Linux Demo Index
Back to Home
Neil Rieck
Waterloo, Ontario, Canada.