Linux下用gSOAP开发Web Service服务端和客户端程序

2019-07-12 18:13发布

Linux下用gSOAP开发Web Service服务端和客户端程序


网上本有一篇流传甚广的C版本的,我参考来实现,发现有不少问题,现在根据自己的开发经验将其修改,使用无误;另外,补充同样功能的C++版本,我想这个应该更有用,因为能用C++,当然好过受限于C。


1、gSOAP的安装:


到http://sourceforge.net/projects/gsoap2/去下载最新版本,目前是:2.7.15


简单安装:


configure --prefix=/usr/local/gSOAP


       make


       make install


为了后面的C和C++版本的服务和客户端的开发能够脱离源代码目录,最好还要如下处理:


(1)将源代码目录下gsoap子目录中的import目录拷贝到gSOAP目录下来;


(2)gSOAP目录下建一个env目录,将gsoap/samples/link下的所有文件拷贝过来,并且生成envC.o(C版本要用到),方法是:


/usr/local/gSOAP/bin/soapcpp2 -penv -c env.h


g++ -c -I /usr/local/gSOAP/include envC.c


(3)gSOAP目录下建一个src目录,将将源代码目录下gsoap子目录中的stdsoap*.*拷贝过来。




2、功能说明:


       要开发的Web Service功能非常简单,就是一个add函数,将两个参数相加,返回其和。


3、C版本的程序:


(1)头文件:SmsWBS.h


//gsoap ns service name: SmsWBS
//gsoap ns service style: rpc
//gsoap ns service namespace: http://192.168.1.88:9000/SmsWBS.wsdl
//gsoap ns service location: http://192.168.1.88:9000
//gsoap ns service encoding: encoded
//gsoap ns schema namespace: urn:SmsWBS


int ns__add(int num1, int num2, int *sum);
这个头文件需要注意的是,前面的 // 部分是有意义的,可以在上面修改,如果完全去掉,将会导致生成的中间文件不同,由此会引起要修改Makefile文件                                           


(2)Makefile文件:


比较关键,如果头文件中的 // 部分有修改,要检查是否要修改Makefile文件


GSOAP_ROOT=/usr/local/gSOAP
WSNAME0=soap
WSNAME=SmsWBS
CC=g++ -g -DWITH_NONAMESPACES
INCLUDE=-I $(GSOAP_ROOT)/include
SERVER_OBJS=$(WSNAME0)C.o $(WSNAME0)Server.o stdsoap2.o
CLIENT_OBJS=$(GSOAP_ROOT)/env/envC.o $(WSNAME0)ClientLib.o stdsoap2.o
ALL_OBJS=${WSNAME}server.o $(WSNAME0)C.o $(WSNAME0)Server.o ${WSNAME}test.o $(WSNAME0)ClientLib.o
#GSOAP_SRC=/usr/local/gsoap-2.7/gsoap


all:server


${WSNAME}.wsdl:${WSNAME}.h
        $(GSOAP_ROOT)/bin/soapcpp2 -c $(GSOAP_ROOT)/import ${WSNAME}.h


stdsoap2.o:$(GSOAP_ROOT)/src/stdsoap2.c
        $(CC) -c $? $(INCLUDE)


$(ALL_OBJS):%.o:%.c
        $(CC) -c $? $(INCLUDE)


server:Makefile ${WSNAME}.wsdl ${WSNAME}server.o $(SERVER_OBJS)
        $(CC) ${WSNAME}server.o $(SERVER_OBJS) -o ${WSNAME}server


client:Makefile ${WSNAME}.wsdl ${WSNAME}test.c $(ALL_OBJS) stdsoap2.o
        $(CC) ${WSNAME}test.o $(CLIENT_OBJS) -o ${WSNAME}test


clean:
        rm -f *.o *.xml *.a *.wsdl *.nsmap $(WSNAME0)H.h $(WSNAME0)C.c $(WSNAME0)Server.c $(WSNAME0)Client.c $(WSNAME0)Stub.* $(WSNAME)$(WSNAME)Proxy.* $(WSNAME)$(WSNAME)Object.* $(WSNAME0)ServerLib.c $(WSNAME0)ClientLib.c $(WSNAME)server ns.xsd $(WSNAME)test




(3)服务端程序SmsWBSserver.c:


#include "soapH.h"
#include "SmsWBS.nsmap"


int main(int argc, char **argv)
{
        int m, s;               /* master and slave sockets */
        struct soap SmsWBS_soap;


        soap_init(&SmsWBS_soap);


        soap_set_namespaces(&SmsWBS_soap, namespaces);


        if (argc < 2)
        {
                printf("usage: %s ", argv[0]);
                exit(1);
        }
        else
        {
                m = soap_bind(&SmsWBS_soap, NULL, atoi(argv[1]), 100);
                if (m < 0)
                {
                        soap_print_fault(&SmsWBS_soap, stderr);
                        exit(-1);
                }


                fprintf(stderr, "Socket connection successful: master socket = %d ", m);


                for (;;)
                {
                        s = soap_accept(&SmsWBS_soap);


                        if (s < 0)
                        {
                                soap_print_fault(&SmsWBS_soap, stderr);
                                exit(-1);
                        }


                        fprintf(stderr, "Socket connection successful: slave socket = %d ", s);
                        soap_serve(&SmsWBS_soap);
                        soap_end(&SmsWBS_soap);
                }


       }


        return 0;
}


int ns__add(struct soap *add_soap, int num1, int num2, int *sum)
{
        *sum = num1 + num2;
        return 0;
}




(4)客户端程序SmsWBStest.c:


#include
#include
#include "soapStub.h"
#include "SmsWBS.nsmap"


int add(const char *server, int num1, int num2, int *sum);


int add(const char *server, int num1, int num2, int *sum)
{
        struct soap SmsWBS_soap;
        int result = 0;


        soap_init(&SmsWBS_soap);
        soap_set_namespaces(&SmsWBS_soap, namespaces);


        soap_call_ns__add(&SmsWBS_soap, server, "", num1, num2, sum);


        if(SmsWBS_soap.error)
        {
                printf("soap error:%d, %s, %s ", SmsWBS_soap.error, *soap_faultcode(&SmsWBS_soap), *soap_faultstring(&SmsWBS_soap));
                result = SmsWBS_soap.error;
         }


        soap_end(&SmsWBS_soap);
        soap_done(&SmsWBS_soap);


        return result;
}


int main(int argc, char **argv)
{
        int result = -1;
        char* server="http://localhost:9000";


        int num1 = 0;
        int num2 = 0;
        int sum = 0;


        if( argc < 3 )
        {
                printf("usage: %s num1 num2 ", argv[0]);
                exit(0);


        }


        num1 = atoi(argv[1]);
        num2 = atoi(argv[2]);


        result = add(server, num1, num2, &sum);
        if (result != 0)
        {
                printf("soap err, errcode = %d ", result);
        }
        else
        {
                printf("%d + %d = %d ", num1, num2, sum);
        }


        return 0;
}




(5)编译和运行:


前面都已经准备好了,现在只需要:


make                                     ---得到服务端程序SmsWBSserver


make client                            ---得到客户端程序SmsWBStest


SmsWBSserver 9000             ----运行服务端程序


出来类似下面的显示就表示运行正常


Socket connection successful: master socket = 3


再运行客户端程序:


SmsWBStest 67 78


显示:


67 + 78 = 145


调用Web Service成功
增加字符串接口:头文件增加:int ns__itoa(int i, char **a); 实现文件增加:
  1. // 服务消息的实现代码  
  2. int ns__itoa(struct soap *soap, int i, char **a)   
  3. {   
  4.     *a = (char*)soap_malloc(soap, 11);   
  5.     sprintf(*a, "%d", i);   
  6.     return SOAP_OK;