• gsoap使用总结


    >>用C实现WebService,gsoap是最好的选择了。近一个月都在折腾这个,做个总结吧,估计会写得比较长。因为其中碰到了不少问题,但最终都解决调了。
    >>快速开始
      1. gsoap官网。遇到问题时,官网往往是最能提供帮助的地方。
         http://gsoap2.sourceforge.net/
      2. 几个值得参考的链接。
         GSoap使用心得: http://www.cppblog.com/qiujian5628/archive/2008/10/11/54019.html
         GSoap接口定义: http://blog.sina.com.cn/s/blog_5ee9235c0100de3g.html
        
    >>测试代码
      我是在linux下用C开发的,那就Makefile入手吧。至于服务端的代码,和客户端的代码,可以参考《GSoap使用心得》,或者是gsoap自带的例子。
         a. 用soapcpp2生产gsoap相关代码: $(GSOAP_BIN)/soapcpp2 -c -x ${WSNAME}.h
         b. 服务端所需的代码: soapC.c soapServer.c stdsoap2.c
         c. 客户端所需的代码: soapC.c soapClient.c stdsoap2.c
         d. 其中stdsoap2.c是从gsoap开发包中复制过来的,他的文件是(a)中命令产生的。
        
    -------------分隔符------------------------------------
    GSOAP_BIN=/usr/local/gSOAP/bin
    WSNAME0=soap
    WSNAME=SmsWBS
    SERVER_OBJS=$(WSNAME0)C.o $(WSNAME0)Server.o stdsoap2.o    ${WSNAME}server.o
    CLIENT_OBJS=$(WSNAME0)C.o $(WSNAME0)Client.o stdsoap2.o    ${WSNAME}client.o
    AA_OBJS=$(WSNAME0)C.o $(WSNAME0)Server.o $(WSNAME0)Client.o stdsoap2.o ${WSNAME}server.o ${WSNAME}client.o

    INCLUDE=
    LIBS=
    CC=g++ -g -DWITH_NONAMESPACES

    #LIBS=-lz -lc -lncurses -lssl -lcrypto
    #CC=g++ -g -DWITH_NONAMESPACES -DWITH_OPENSSL

    all:server
    all:client


    ${WSNAME}.wsdl:${WSNAME}.h
        $(GSOAP_BIN)/soapcpp2 -c -x ${WSNAME}.h

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

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

    client:Makefile ${WSNAME}.wsdl  $(CLIENT_OBJS)
        $(CC) $(CLIENT_OBJS) $(LIBS) -o Smsclient

    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

    clear:
        rm -f *.o ns.xsd
    -------------分隔符------------------------------------


    >>接口定义,可参考《GSoap接口定义》。这里我将给出C#引用这个webserver所对应的接口形式。
      gsoap是根据我们定义好的.h文件,然后用工具产生了我们所需的.c文件。所以我们必须根据gsoap的要求编写.h。
      1. 单个参数的传出:
         int ns__add( int a, int b, int *c );
         需要说明的是,这里的ns__是必须的,必须以开始注释中的ns加两个下划线开始。返回值必须是int。
         但是这里的int并不是接口的返回值,而是gsoap内部的返回值。真正的返回值是int *c。
        
         C#中对应的接口:  int add( int a, int b );  返回值就是上述的int *c参数。
        
      2. 多个参数传出,在接口中必须使用结构体
         typedef char * xsd__string;
         typedef long   xsd__int;
         struct ns__personResponse{
             xsd__int age;
             xsd__string name;
             xsd__string address;
         };
         int ns__person( xsd__string buf_in, struct ns__personResponse * buf_out );
        
         在C#中,并不是我们所声明的这样。而是:int person( string buf_in, out string name, out string address );
         即,结构体中的第一个域会变成返回值,其他的变成一个个的输出参数。
        
      3. 返回结构体。如果要返回结构图,那么必须在结构体中再套一层结构体:
         typedef char * xsd__string;
         typedef long   xsd__int;
         struct ns__person{
             xsd__int age;
             xsd__string name;
             xsd__string address;    
         };
         struct ns__personResponse{
             xsd__int ret;
             struct ns__person person;
         };
         int ns__person( xsd__string buf_in, struct ns__personResponse * buf_out );
        
         那么在C#中,看到的接口是这样的:int person( string buf_in, person对应的结构类 );
        
      4. 接口中的下划线,如果接口中的交易名有下划线,必须这么声明:
         int ns__echo_USCOREreverse( char * buf_in, char ** buf_out );
        
         那么,C#中实际上的接口名就是:string echo_reverse( string buf_in );

      
    >>gsoap中返回字符串
      1. 下面是一个逆转字符串的函数。
         int ns__echo_USCOREreverse( char * buf_in, char ** buf_out );
         int ns__echo_USCOREreverse( struct soap *add_soap, char *buf_in, char **buf_out )
         {
            int i, j, len;
            printf( "ns__interface: in=[%s]\n", buf_in );
       
            len = strlen(buf_in);
            *buf_out = (char*)soap_malloc( add_soap, len+1 );
            for( i=len-1, j=0; i>=0; i--, j++ ){
                (*buf_out)[j] = buf_in[i];
            }
            (*buf_out)[j] = 0;

            return 0;
         }
        
         其中调用soap_malloc申请空间,并且将他赋给返回参数buf_out。这个空间会在调用soap_end时被释放。
        
    >>gsoap传输中文。我使用utf-8编码格式来支持汉字的传输。
      1. 设置gsoap为utf-8传输数据
         soap_set_mode( &SmsWBS_soap, SOAP_C_UTFSTRING );    //设置编码
         SmsWBS_soap.mode|=SOAP_C_UTFSTRING;
        
      2. 使用下面得函数转换我们的传输内容,即将我们的数据转成UTF-8编码:
         int conv_charset( const char *dest, const char *src, char *input, size_t ilen, char *output, size_t olen )
         {
             int convlen = olen;
             iconv_t conv = iconv_open( dest, src );
             if( conv == (iconv_t) -1 )
                 return -1;
       
              memset( output, 0, olen );
             if( iconv( conv, &input, &ilen, &output, &olen ) ){
                 iconv_close(conv);
                 return -1;
             }

             iconv_close(conv);
             return convlen-olen;
         }
         例子: conv_charset( "UTF-8", "GBK", "林学任.linxr", strlen("林学任.linxr"),  buf_out->name, 100 );
     
    >>webserver发布
      1. 在C#中,可以直接引用一个webserver,但是我们写得webserver如何能用被其引用呢。其实只要实现gsoap的fget回调函数即可:
         SmsWBS_soap.fget = http_get;
      2. http_get函数实现
         int http_get(struct soap * soap)
         {
             FILE *fd = NULL;
        
             char *s = strchr( soap->path, '?' );
             if( !s || strcmp( s, "?wsdl" ) ){
                 return SOAP_GET_METHOD;
             }
        
             fd = fopen( "SmsWBS.wsdl", "rb" );
             if (!fd){
                 return 404;
             }
        
             soap->http_content = "text/xml";
             soap_response(soap, SOAP_FILE);
             for (;;){
                 size_t r = fread(soap->tmpbuf, 1, sizeof(soap->tmpbuf), fd);
                 if( !r ){
                     break;
                 }
                 if( soap_send_raw( soap, soap->tmpbuf, r) ){
                     break;
                 }
             }
        
             fclose(fd);
             soap_end_send(soap);
        
             return SOAP_OK;
         }
        
        

  • 相关阅读:
    [大话数据结构]线性表之单链表结构和顺序存储结构
    [大话数据结构]算法
    [C#编程参考]把图像转换为数组的两种实现
    [C#绘图]在半透明矩形上绘制字符串
    [C#绘图]Matrix类
    在C#调用C++的DLL方法(二)生成托管的DLL
    在C#调用C++的DLL方法(一)生成非托管dll
    彻底解决 LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
    修复./mysql/proc
    linux 网络连接数查看方法
  • 原文地址:https://www.cnblogs.com/linxr/p/2215285.html
Copyright © 2020-2023  润新知