新年伊始,想把onvif和gsoap boa这三个东西学习下,并作下笔记,当然为了省时间,我昨天下午看了一个下午的gsaop官网pdf感触良多,也做了小测试,废话少说,一下也有一些是摘自网友博客,大部分和pdf上说的翻译版,所以有好多雷同;

http://www.cnblogs.com/linxr/archive/2011/10/17/2215285.html

http://www.cs.fsu.edu/~engelen/soap.html

http://g.51cto.com/flower454/66952

http://www.cppblog.com/pansunyou/archive/2013/08/05/137563.html

http://www.cppblog.com/pansunyou/archive/2013/08/05/137563.html

http://software.intel.com/zh-cn/blogs/2013/05/09/gsoap实现高性能服务inter

http://www.cppblog.com/woaidongmao/archive/2008/05/28/51400.html 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;
     }

gsoap 学习 1-如何使用的更多相关文章

  1. gsoap 学习 1-自己定义接口生成头文件

    接口头文件的格式在向导中没有看到明确的说明性的内容,但通过看开发包中示例程序中头文件定义和通过wsdl生成的头文件的内容,可以发现,头文件中都会出现以下几行信息 //gsoap ns service ...

  2. gsoap 学习 1-由wsdl文件生成h头文件

    开始前先看一下用户向导吧 http://www.cs.fsu.edu/~engelen/soap.html 中左侧点击Documentation 英语水平确实有限,有些内容可能说的不准确,敬请参考向导 ...

  3. gSoap学习笔记

    http://www.cnblogs.com/xiangism/archive/2012/11/14/2770242.html http://www.cnblogs.com/lvkun/archive ...

  4. [转贴]gsoap使用心得!

    最近换了个工作环境,现在在大望路这边上班,呵,刚上班接到的任务就是熟悉gsoap!废话少说,现在开始gSoap学习! gSOAP是一个夸平台的,用于开发Web Service服务端和客户端的工具,在W ...

  5. 在别的地方看的<<给程序员介绍一些C++开源库>>,记录给大家共同学习

    首先说明这篇文章不是出自我手,大家共同学习. 引用地址:http://oss.org.cn/?action-viewnews-itemid-61998. C++开源库,欢迎补充. C++在“商业应用” ...

  6. win7 gsoap与vs2010 c++创建Web Service

    ---恢复内容开始--- 之前曾经编写过简单的样例,很久没有碰过,发现已经全部忘记,如今又需要重新巩固一下. 首先是下载gsoap,无法访问官方下载页面,只能在网上搜索,找到一个2.8版本存入云盘以防 ...

  7. Ubuntu下安装gsoap

    昨天在ubuntu下进行安装gSOAP,费了很多时间,没成功,今天又来找了大量教程资料,终于一次成功,这里写下自己的安装步骤和方法,供大家参考. 首先下载gsoap,我下载的是gsoap-2.8.1. ...

  8. C#作为客户端调用gsoap生成的C++服务端

    近日在学习C++,偶然遇到网友想用C#调用gsoap生成的C++服务的问题,遂决定研究一下,网上搜索了很久,大多数是C++调用C#的应用.... 经过本人的不断努力,终于找到一种解决问题的方法,总结如 ...

  9. vc++2008 采用GSoap访问 WebService

    (转http://www.cppblog.com/yeqing/articles/12762.html) 前一阶段写gSOAP 的文章没保存好,后来想写的,越学越没有写的勇气了,感觉自己很菜,但是现在 ...

随机推荐

  1. python标准库介绍——18 StringIO 模块详解

    ==StringIO 模块== [Example 2-8 #eg-2-8] 展示了 ``StringIO`` 模块的使用. 它实现了一个工作在内存的文件对象 (内存文件). 在大多需要标准文件对象的地 ...

  2. linux系统中用户切换

    1. Linux系统中用户切换的命令为su,语法为: su [-fmp] [-c command] [-s shell] [--help] [--version] [-] [USER [ARG]] 参 ...

  3. redis 只允许指定的额内网IP访问,其余的外网IP不允许访问

    为了redis的安全,现在设定如下规则.只允许指定的服务器通过内网的方式访问.其余一律不准访问 因为redis登录额时候是不需要密码的,很不安全. 所以这里添加如下iptables规则 iptable ...

  4. MYSQLDUMP参数详解(转)

    mysqldump客户端可用来转储数据库或搜集数据库进行备份或将数据转移到另一个SQL服务器(不一定是一个MySQL服务器).转储包含创建表和/或装载表的SQL语句. 如果你在服务器上进行备份,并且表 ...

  5. C语言 函数参数不确定时 需要用到va_start和va_end函数

    1.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表 void foo(...);void foo(parm_list,...); 这种方式和我们以前认识的不大一样,但我 ...

  6. 大数问题:求n的阶乘

    题目:求100! 这看起来是一个非常简答的问题,递归解之毫无压力 int func(int n){ if(n <= 1) return 1; else return n*func(n-1); } ...

  7. Amoeba软件实现mysql读写分离

    一般不用,大公司都是自己程序实现的. 安装amoeba

  8. [svc]linux日志和安全日志

    last详解: http://www.cnblogs.com/kerrycode/p/4223751.html

  9. CCCallFunc和CCSequence

    class CC_DLL CCCallFunc : public CCActionInstant //<NSCopying> void Issue1305_2::onEnter() { A ...

  10. JVM总结篇

    Sun HotSpot VM,是JDK和Open JDK中自带的虚拟机,也是目前使用范围最广的Java虚拟机. JVM内存分布 程序计数器:是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号 ...