gsoap中文乱码及内存清理等问题的解决方案

简介: gsoap中文乱码的问题 -- 拔剑,2010-08-31 一、 问题和分析 gsoap在调用Webservice过程中,如果字符串中有汉字,很容易出现乱码。
gsoap中文乱码的问题

 -- 拔剑,2010-08-31

 

一、 问题和分析

 

gsoap在调用Webservice过程中,如果字符串中有汉字,很容易出现乱码。 由于网络间一般用UTF8表示

字串(ANSI字串- (char < 128)本身已经符合UTF8编码规则),所以ANSI字符不会乱码,而一个汉字

的传统表示需要两个字符,而在wchar_t宽字符串中只需一个字符表示。

 

一个汉字用UTF8表示通常占用3个BYTE, 如:

         你  --〉0xe4, 0xbd, 0xa0

         好  --> 0xe5, 0xbd, 0x21

 

gSoap在封装XML包时,在进行utf8字符转换时:

   1)如果入口参数为 char* / std::string (即用多字节表示汉字)时,

      汉字因为已经用2个字节(窄字符)表示,此时的UTF8编码已近不是对该汉字的码值编码,

      而是对组成该汉字的两个字符进行utf8编码,结果自然不对了。因此乱码。

                    UTF8(0xAABB)   !=  UTF8(0XAA + 0XBB)

   2)如果入口参数为 wchar_t* / std:wstring(即一个汉字用一个字符表示)时,

      汉字因为用1个宽字符表示(两个字节),因此UTF8转换没有问题。

 

gSoap在解包时,因为来源字符串已经用UTF8表示,因此在gsoap的response中,用std::string/char*,

道理上,在转换到当前字符集,应该不会乱码。

 

二、解决方案

 

   很简单,在gsoap的数据类型中,用wchar_t* 或std::wstring代替std:string/char*.同时,

为了确保Proxy类用UTF8编解码,可以在其构造函数中强行赋编码方式,如:   

          MyServiceSoapProxy gs(SOAP_C_UTFSTRING); 

 

由于gsoap的调用代码是自动生成的,如何办?

   我们需要在生成gSoap调用代码时,强制使用wchar_t*/std::wstring. 我们可以修改default类型转换

文件或者强制使用某个类型转换文件。如:

gSOAP两大工具的用法从WSDL中产生头文件,用法:
    wsdl2h -o 头文件名 WSDL文件名或URL
    wsdl2h常用选项
    -o 文件名,指定输出头文件
    -n 名空间前缀 代替默认的ns
    -c 产生纯C代码,否则是C++代码
    -s 不要使用STL代码
    -t 文件名,指定type map文件,默认为typemap.dat
    -e 禁止为enum成员加上名空间前缀
 type map文件用于指定SOAP/XML中的类型与C/C++之间的转换规则,比如在mytypema.dat(拷贝自default typemap.dat)里写
    xsd__string = | std::wstring | wchar_t*    # 注释符号为#
 那么SOAP/XML中的string将转换成std::wstring或wchar_t*,这样能更好地支持中文。

 例:

    wsdl2h -o ws.h  -n ws -t mytypemap.dat \ http://www.aaa.com/Service.asmx?WSDL
    从http://www.aaa.com/Service.asmx?WSDL 生成ws.h文件,名空间为ws,使用mytyemap.dat指定的转换规则。

 

三、一点说明

  1)入口参数,用局部变量的地址付给参数,避免内存分配销毁

  2)gSoap will use soap_malloc(..) to allocate memory, which is different from malloc()/new

     you should NOT delete memory allocated by gsoap by yourself in Response Object.

 

        GSOAP CAN AUTOMATICALLY DELETE THOSE MEMORIES IT ALLOCATED!!!!!!

 

     If you tried to delete those memory allocated by gSOAP, memory leak could appear.

     (Maybe to use soap_delete(soap*, pointer) is safe, not fully tested, and no need!)

  3)不支持__int64 (如表示时间)

     simple, directly comments out conditional macro covering

              gsoap_s2LONG64(...)

              gsoap_LONG642s(...)

     like:

             //#ifndef XXXX

             //#endif

  4) __int64转换失败问题(时间是用__int64表示的)

     In windows, use "%I64d" instead of "%lld".

  5)同时调用多个Web service接口

     自需要把Web service的WSDL文件放在一起给wsdl2h调用,如:

         wsdl2h -o ws.h -n ws -t mytypemap.dat WSDL_file1 WSDL_File2 .... WSDL_FileN

     生成的文件中,ENDPOINT被写在一个字串里面,因此需要修改生成的源代码

        const char* ENDPOINT ="http_url1  http_url2 http_url3 .. http_urlN";

     ===>

        contst char* END_POINT_IF1 = "http_url1";

        const  char* END_PINT_IF2 = "http_url2" ;

       ...

        const char* END_POIINT_IFN = "http_urlN";

    ==> 同时修改每个Webservice调用的Endpoint值,用END_POINT_IF1,....END_POINT_IFN分别替代。

 7) you can use soap_malloc(..) to create temp memory, and soap will automatically delete

    such kind of data in Proxy destructor.

 

    If you want to delete the memory by yourself, or even after soap object (Proxy) is destructed.

    You  can use

                         soap_unlink(...)

    to de-reference this allcocated memory and later use

                         free(...)

    to release the memory by yourself.

  8) Do not copy Soap PROXY instance, otherwise could cause memory issue. You can use pointer,

     or reference type to pass such parameters.

  9)二进制流的传输

     XML利用Base64编码的文本传输二进制流,WebService/gSoap支持无限制长度的二进制流传输。

     在gsoap中要传输二进制流不需要做特别的处理,gsoap会自动将数据进行Base64编解码。

 

 

四、调试

  1)察看gsoap的XML封包可以在下面的函数设置断点:

            gsoap_fsend/fsend

            gsaop_frecev/frecv

  2)数据类型转换

            gsoap_s2LONG64

            gsoap_s2int

            ...

            gsoap_LONG642s

            ...

   3) turn on

            SOAP_DEBUG

      to see more thing.

 

参考:

  http://www.cs.fsu.edu/~engelen/soapdoc2.html#tth_sEc7.2.3

  http://panxq0809.javaeye.com/blog/709173

  (其余忘记了)

相关文章
|
8月前
Mac 内存清理,内存占用过大,瘦身操作
Mac 内存清理,内存占用过大,瘦身操作
119 0
|
3月前
|
弹性计算 运维 搜索推荐
幻兽帕鲁内存溢出怎么办,一键设置定时重启,修改虚拟内存,定时清理,轻松解决卡顿!再也不怕爆内存了!
幻兽帕鲁的内存溢出问题,玩久了确实会变卡。这里给出三个解决思路:第一种方法是定时进行内存清理(装个软件就可以),网上也有很多教程,我会把下载地址放在文章后面,大家可以去下载。第二种方法是调大虚拟内存,这个可以一键设置。第三种方法是定时重启游戏服务,这个也可以一键设置。这三种方法我下面都会教给大家,可以有效解决内存增长过快的问题,避免游戏卡顿甚至崩溃。
488 3
|
5天前
|
Android开发
Android 设备清理内存 RAM
Android 设备清理内存 RAM
9 0
|
2月前
|
Linux
linux杀死CPU占用过高内存占用过高定时清理
linux杀死CPU占用过高内存占用过高定时清理
13 0
|
4月前
|
存储 监控 NoSQL
【Redis深度专题】「核心技术提升」从源码角度探究Redis服务的内存使用、清理以及逐出等底层实现原理
Redis作为一种高性能的内存NoSQL数据库,其容量受限于最大内存的限制。用户在使用阿里云Redis时,除了对性能和稳定性有较高的要求外,对内存占用也非常敏感。然而,在实际使用中,一些用户可能会发现他们的线上实例的内存占用比预期的要大。
69 1
【Redis深度专题】「核心技术提升」从源码角度探究Redis服务的内存使用、清理以及逐出等底层实现原理
|
5月前
|
缓存 C# Windows
一款.NET开源的小巧、智能、免费的Windows内存清理工具 - WinMemoryCleaner
一款.NET开源的小巧、智能、免费的Windows内存清理工具 - WinMemoryCleaner
|
6月前
|
Shell
使用 shell 脚本清理内存 buff/cache
使用 shell 脚本清理内存 buff/cache
115 0
|
9月前
|
监控 Shell Linux
linux实现shell脚本监控磁盘内存达到阈值时清理catalina.out日志
linux实现shell脚本监控磁盘内存达到阈值时清理catalina.out日志
251 0
内存清理、动画制作、CPU检测等五款实用软件推荐
人类与99%的动物之间最大差别在于是否会运用工具,借助好的工具,能提升几倍的工作效率。
261 0
内存清理、动画制作、CPU检测等五款实用软件推荐
|
缓存 安全
CleanMyMac X稳定版苹果电脑磁盘内存清理软件
Mac电脑用的时间久了,Mac用户尤其是MacBook用户会经常收到“磁盘几乎已满”的提示,如何解决这个问题,当我们使用苹果MAC一段时间后,就会有大量的垃圾文件占用磁盘空间,例如系统缓存文件、应用程序缓存文件、备份和重复文件、旧版的应用程序及其部件等,为了不影响电脑的后续使用,我们需要经常清理磁盘空间,这里分享一个处理磁盘空间不足提示的小方法。CleanMyMac X下载:http://t.csdn.cn/ye9sT
121 0