最近libcurl不能支持毫秒级的超时问题,在第三方接口出现问题的时候由于超时问题容易挂住我们的server,因此考虑自己写一个http协议处理的类,来处理向第三方的http协议接口请求数据的问题。首先一个问题是处理http响应数据经过压缩后的解压问题。这里必然选择zlib库。
1.8...15 压缩格式为zlib
header包裹的deflate原始数据;
2.-8...-15
压缩格式为原始的deflate数据;
3.8...15 + (32) 压缩格式为zlib header或者gzip
header包括的deflate原始数据。
第三种情况要求zlib的version大于等于1.2.0.4,如果小于干版本好,那么必须自己处理对应的gzip
header,然后再解压原始的deflate数据。写了一个简单的解压函数如下,方便没有接触过zlib的兄弟们了解解压Http
Rsp的过程。
uncompress.h
#ifndef __UNCOMPRESS_H__
#define __UNCOMPRESS_H__
#include "zlib.h"
#include <string>
using namespace std;
class CUncompress
{
public:
CUncompress(string & sUncompressData);
~CUncompress();
public:
int Init(char * pszCompressed, int nCompressedLen, bool
bIsGzip=false);
int UncompressData();
char * GetErrMsg()
{
return m_szErrMsg;
}
private:
string & m_sData;
char * m_pszDataChunk;
z_stream m_objStream;
char m_szErrMsg[1024];
bool m_bIsGzip;
};
#endif
uncompress.cpp
#include "uncompress.h"
#include <string.h>
static const int DSIZE = 0x10000;
CUncompress::CUncompress(string &
sUncompressData):m_sData(sUncompressData)
{
memset(m_szErrMsg, 0, 1024);
m_pszDataChunk = new char[DSIZE];
m_bIsGzip = false;
}
CUncompress::~CUncompress()
{
if (m_pszDataChunk != NULL)
{
delete [] m_pszDataChunk;
}
}
int CUncompress::Init(char * pszCompressed, int
nCompressedLen, bool bIsGzip)
{
int nErrCode = 0;
m_objStream.zalloc = (alloc_func)Z_NULL;
m_objStream.zfree = (free_func)Z_NULL;
m_objStream.opaque = 0;
m_objStream.next_in = NULL;
m_objStream.avail_in = 0;
if (bIsGzip)
{
m_bIsGzip = true;
if (strcmp(zlibVersion(), "1.2.0.4") < 0)
{
snprintf(m_szErrMsg, 1024, "zlib version <
1.2.0.4");
return -1;
}
if ((nErrCode = inflateInit2(&m_objStream,
MAX_WBITS + 32)) != Z_OK)
{
snprintf(m_szErrMsg, 1024, "inflateInit2 failed, err code=%d",
nErrCode);
return -2;
}
}
else
{
if ((nErrCode = inflateInit(&m_objStream)) !=
Z_OK)
{
snprintf(m_szErrMsg, 1024, "inflateInit failed, err code=%d",
nErrCode);
return -3;
}
}
m_objStream.next_in = (Bytef*)pszCompressed;
m_objStream.avail_in = (uInt)nCompressedLen;
return 0;
}
int CUncompress::UncompressData()
{
bool bRetry = true;
uInt unRead = m_objStream.avail_in;
Bytef * pszInData = m_objStream.next_in;
int nStatus = 0;
for (;;)
{
m_objStream.next_out = (Bytef*)m_pszDataChunk;
m_objStream.avail_out = DSIZE;
nStatus = inflate(&m_objStream,
Z_SYNC_FLUSH);
if (nStatus == Z_OK || nStatus == Z_STREAM_END)
{
bRetry = false;
if (DSIZE - m_objStream.avail_out)
{
m_sData.append(m_pszDataChunk, DSIZE -
m_objStream.avail_out);
}
if (nStatus == Z_STREAM_END || (nStatus == Z_OK
&& m_objStream.avail_in ==
0))
{
if ((nStatus = inflateEnd(&m_objStream)) ==
Z_OK)
{
return 0;
}
else
{
snprintf(m_szErrMsg, 1024, "inflateEnd failed, err code=%d",
nStatus);
return -1;
}
}
}
else if ((!m_bIsGzip) &&
bRetry && nStatus ==
Z_DATA_ERROR)
{
//if has no zlib header, try another way
(void)inflateEnd(&m_objStream);
if ((nStatus = inflateInit2(&m_objStream,
-MAX_WBITS)) != Z_OK)
{
snprintf(m_szErrMsg, 1024, "data has no zlib header, try
another way inflateInit2 failed, err cod=%d", nStatus);
return -2;
}
m_objStream.next_in = pszInData;
m_objStream.avail_in = unRead;
bRetry = false;
continue;
}
else
{
(void)inflateEnd(&m_objStream);
snprintf(m_szErrMsg, 1024, "error when inflate compressed, err
code=%d", nStatus);
return -3;
}
}
return 0;
}
后一篇:markupSTL使用
后一篇 >markupSTL使用


加载中…