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.