使用比HttpSocket更简单.
在HttpSocket基础上改的例子,也是下载一个URL文件,不过这儿更简单,只需要URL和文件名就可以得到了.
#include
#include
#include
using namespace std;
class MyHttp : public HttpGetSocket
{
public:
MyHttp(SocketHandler& h,string url,string filename): HttpGetSocket(h,url,filename) {}
};
理解一下:
在HttpSocket类的基础上,HttpGetSocket重载了
OnHeader()
OnFirst()
OnContent()
OnConnect()
OnDelete()
OnHeaderComplete()
OnData()
这几个函数.
OnHeaderComplete()函数有意思,当HTTP头文件传输完后,这个函数被除数调用,它检查内定的文件名变量是否被赋值,如果已被赋值,它将自动打开一个可写文件,以二进制模式,把文件指针保存起来.
HttpSocket类里说过,OnData函数能接收HTTP实体部分.这儿也一样.只不过多了个OnContent的调用.在OnContent里检查文件指针是否有效,如有效则把数据写入此文件.
OnDelete函数里也有对OnContent的调用,保存一下已收到的数据这也是一个机会.
辅助函数
url_this,url这两个函数是把URL解析为内定变量,如host,port,file等.
SetDataPtr(),GetDataPtr()是设置缓冲区的,可以自己指定,也可以不指定.
不指定时会自动创建一个.无须费心.可以参考OnHeader一节
如果自己想处理细节,还是用HttpSocket类.看来看去,HttpGetSocket都是为了下载文件准备的,如果不用这个功能,不如直接用HttpSocket和TcpSocket.
由于HttpGetSocket下载大文件时会占用大量内存,如果下载200M的还可以接受,如果1G的话就不可想象了.下面是偶改的代码:下载208M的文件也只用10M以内的内存.
新加变量:
size_t m_minLimitOfWrite; ///< 这是偶自定的变量,到了1024*1024以上就写入文件并归零变量
修改OnData函数如下:
//只需设一个很小的自定义缓冲区,便会使 m_content_ptr + len > m_data_max 条件为真,从而避开memcpy.
void HttpGetSocket::OnData(const char *buf,size_t len)
{ //缓冲区iBuf已经接收了数据,把指针传过来,如果不是为了兼容原代码,这儿直接写文件即可.有些代码可删.
if (m_content_ptr + len > m_data_max)
{
Handler().LogError(this, "OnData", -1, "content buffer overflow", LOG_LEVEL_ERROR);
}
else
{ //如果缓冲区太小不能容纳大量数据,则不写入缓冲区,直接写入文件.可以设一个小缓冲区避开memcpy
memcpy(m_data + m_content_ptr, buf, len);
} //如果我需要buf中的内容,直接重载OnData即可,这儿copy一下,内存利用不好
if (m_fil)
{
fwrite(buf,1,len,m_fil);
}
m_content_ptr += len;
m_minLimitOfWrite += len;
if (m_content_length > 0 && (m_minLimitOfWrite>=(1024*1024) || m_content_ptr== m_content_length))
{ //自定义的 m_minLimitOfWrite>=(1024*1024) 使接收到1M字节就写入文件,对于大文件尤其重要
OnContent();
m_minLimitOfWrite =0;
}
}
修改OnContent函数如下:
void HttpGetSocket::OnContent() //在OnData中被调用,
{
if (m_fil)
{
fflush(m_fil); //写入文件,只有HTTP实体部分
if(m_content_ptr!= m_content_length) //这是偶加的,不收完继续,收完关闭文件
return;
fclose(m_fil);
}
m_fil = NULL;
SetCloseAndDelete(true);
m_bComplete = true;
}
使用时如下:
unsigned char buf[1];
...
HttpGetSocket get(.....);
get.SetDataPtr(buf,1);
用一个小缓冲区避开HttpGetSocket分配和下载文件一样大小的缓冲区.因为有了ibuf的缓冲区,所以我们不设自己的了,直接写入文件即可.
如果分配了缓冲区,还要从ibuf里往我们的缓冲区里copy,不知道原作者怎么考虑的?期待有人能给偶个解答.
哪天查查英语词典,上官方网发贴问一下.
猜想一下,如果不考虑大文件的话,仅对网页文件,原代码的效果还是很好的.空间换时间?偶不知道.
阅读(1726) | 评论(2) | 转发(0) |