找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 4413|回复: 0

基于MS SoapClient的数据压缩方法

[复制链接]
发表于 2008-9-21 18:12:23 | 显示全部楼层 |阅读模式
Ms soap应用大大简化了客户端与服务器数据库的交互过程,自动实现了于webservice的交互过程 ,减短了我们的开发时间,同时其灵活性也相当强。但是其通过http传输的数据不支持自动压缩,同时其相关的教程和可查询的资料是少之又少,查遍MSND以及google搜索也很难找到所需的资料,可以说是这个产品中的一大败笔。
众所周知,soap基于xml实现了数据标识以及灵活的扩展,同时由此而产生了大量重复的标识符,压缩比相当高,对于有众多不同网络环境用户的系统而言,clientservice之间进行大量数据传输的时候,由此而产生的数据膨胀是致命的,我们迫切需要对数据进行压缩。
通过搜索引擎我们可以查到一些相关的文章,大都提及到了xml序列化以及反序列化,但是缺少详细的实施步骤。下面笔者以自身切实环境讲述一下详细实施过程:
笔者的客户端环境是vc.net,服务器端apache已经配置了支持gzip压缩的组件,通过抓包分析发现,SoapClient发出的http请求中没有声明可接受gzip压缩数据,服务器发回的应答数据自然也就不会进行gzip压缩,于是笔者在请求头中加入Accept-Encoding: gzip, deflate\r\n,然后抓包分析,服务器返回的应答的确经过了压缩,但是WinINet不会自动自持gzip解压,这个工作在Windows Server“Longhorn” Windows Vista之前的window版本中必须由开发者来完成,对于SoapClient,我们只需要扩展一下ReadStreamOnInetRead方法,加入具体的解压缩代码,把解压后的数据返回给调用者就OK了。
这是具体实施过程吗?呵呵,当然不是,以上只是笔者提纲挈领的表述一下主体过程。客户端具体实施过程可以分为三步:
一、修改CSoapWininetClientSendRequest方法,在发送请求前加入
HttpAddRequestHeaders(m_hRequest, CString("Accept-Encoding: gzip, deflate\r\n"), -1, HTTP_ADDREQ_FLAG_ADD);同时修改请求头中声明的可接受类型,我是修改为:
static LPCTSTR s_szAcceptTypes[] = { _T("text/xml"), _T("text/html"), _T("*/*"), NULL };当然如果你的soapclient使用的是CsoapSocketClient,则修改CsoapSocketClientSendRequest方法。
二、修改CReadStreamOnInetRead方法,把解压后的数据返回给调用者。

HRESULT CGzipReadStreamOnInet::Read(void *pDest, ULONG dwMaxLen, ULONG *pdwRead)

{
         BOOL bRet = TRUE;
         while (bRet && (NULL != m_tmpFile))
         {
                   bRet = InternetReadFile(m_nhFile, pDest, dwMaxLen, pdwRead);
                   if (*pdwRead > 0)
                   {
                            m_tmpFile->Write(pDest, *pdwRead);
                   }
                   else
                   {
                            m_tmpFile->Close();
                            delete m_tmpFile;
                            m_tmpFile = NULL;
                            break;
                   }
         }
         *pdwRead = 0;

         if (NULL == m_gzFile)
         {
                   m_gzFile = gzopen(CT2A(m_tmpFileName), "rb");
         }
         if (NULL == m_gzFile)
                   return E_FAIL;
         int nRead = gzread(m_gzFile, pDest, dwMaxLen);
         if (-1 == nRead)
                   return E_FAIL;
         *pdwRead = nRead;
         return S_OK;

}
三、修改SoapClient中的成员变量m_readStream类型为CGzipReadStreamOnInet
class CGzipSoapClient
{
private:

       CUrl m_url;
       CWriteStreamOnCString m_writeStream;
       CGzipReadStreamOnInet m_readStream;
       CString m_strProxy;
       DWORD m_dwTimeout;
       CFixedStringT<CString, ATL_URL_MAX_URL_LENGTH+1> m_strUrl;
       SOAPCLIENT_ERROR m_errorState;
然后编译,运行,OK

以上是客户端的实施过程,对于服务端,如果你使用的是apache,请参阅http://www.code365.com/tech/0/80/Article/7177.Asp,可以得到具体配置信息。如果你使用的是IIS,可以从[url=http://www.wwwcoder.com/main/parentid/170/site/3669/68/default.aspx]http://www.wwwcoder.com/main/parentid/170/site/3669/68/default.aspx[/url]得到相关信息,但是笔者没有具体实施验证。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-4-29 14:48 , Processed in 0.012107 second(s), 7 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表