// 使用Boost::Asio库, 实现Http的下载
// 使用Boost::Asio库, 不但可以实现下载,
// 而且可以方便的实现断点续传.(以后会补充出来)
// 驳壳地址: http://blog.csdn.net/robertkun
#include "stdafx.h"
#include <boost/asio.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/algorithm/string.hpp>
#include <fstream>
using boost::asio::ip::tcp;
struct HttpResponse
{
public:
explicit HttpResponse(){ clear();}
std::string http_version; // 版本
unsigned int status_code; // 状态码
std::string status_message; // 状态
std::string header; // HTTP包头
std::string body; // HTTP返回的内容
std::string content_type;
std::string modify_time;
unsigned int content_length;
unsigned int total_length;
unsigned int offset;
void clear()
{
http_version.clear();
status_code = -1;
status_message.clear();
header.clear();
content_type.clear();
modify_time.clear();
content_length = 0;
total_length = 0;
offset = 0;
body.clear();
}
};
struct DownloadInfo
{
DownloadInfo()
{
id = 0;
url.clear();
filename.clear();
md5.clear();
writesize = 0;
continued = false;
lasterr = 0;
trycount = 0;
}
int id;
std::string url;
std::string filename;
std::string md5;
int writesize;
bool continued;
int lasterr;
int trycount;
};
// 获取文件
bool GetHttpFile(const std::string& szHost, const std::string& szParam)
{
DownloadInfo* d_diCurrent = new DownloadInfo();
d_diCurrent->filename = "DoLang.wma";
try
{
std::ofstream f_ofsSave;
boost::asio::io_service io_serv;
// Get a list of endpoints corresponding to the server name.
std::string szService ("http");
std::string szIp = szHost;
int i = szHost.find(":") ;
if (i != -1)
{
szService = szHost.substr(i+1);
szIp = szHost.substr(0, i);
}
tcp::resolver::query query(szIp, szService);
tcp::resolver m_resolver(io_serv);
tcp::socket s_socket(io_serv);
tcp::resolver::iterator endpoint_iterator = m_resolver.resolve(query), end_it;
// Try each endpoint until we successfully establish a connection.
tcp::resolver::iterator it = boost::asio::connect(s_socket, endpoint_iterator);
if(it == end_it)
return false;
boost::asio::streambuf request;
{
std::ostream request_stream(&request);
request_stream << "GET " ;
request_stream << szParam << " HTTP/1.1\r\n";
request_stream << "Host: " << szHost << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Pragma: no-cache\r\n";
request_stream << "Cache-Control: no-cache\r\n";
request_stream << "Connection: close\r\n";
request_stream << "\r\n";
boost::asio::write(s_socket, request);
}
// **************************************************************
// 取出数据
// **************************************************************
boost::asio::streambuf response;
std::ostringstream packetStream;
try
{
// Read until EOF, writing data to output as we go.
bool hasReadHeader = false;
boost::system::error_code error;
HttpResponse result;
result.body.clear();
while (boost::asio::read(s_socket, response,
boost::asio::transfer_at_least(1), error))
{
packetStream.str("");
packetStream << &response;
std::string packetString = packetStream.str();
if (!hasReadHeader)
{
// 取出http header
size_t nEndHeader = packetString.find("\r\n\r\n");
if(nEndHeader == std::string::npos)
continue;
hasReadHeader = true;
result.header = packetString.substr(0, nEndHeader);
// *****************************************************
// 分析文件头
// *****************************************************
// Check that response is OK.
std::istringstream response_stream(result.header);
response_stream >> result.http_version;
response_stream >> result.status_code;
std::string strLine;
std::getline(response_stream, strLine);
while (!strLine.empty())
{
if (strLine.find("Content-Type:") != std::string::npos)
{
result.content_type = strLine.substr(strlen("Content-Type:"));
result.content_type.erase(0, result.content_type.find_first_not_of(" "));
}
if (strLine.find("Content-Length:") != std::string::npos)
{
result.content_length = atoi(strLine.substr(strlen("Content-Length:")).c_str());
result.total_length = result.content_length;
}
if (strLine.find("Last-Modified:") != std::string::npos)
{
result.modify_time = strLine.substr(strlen("Last-Modified:"));
result.modify_time.erase(0, result.modify_time.find_first_not_of(" "));
}
if (strLine.find("Content-Range: bytes") != std::string::npos)
{
std::string tmp = strLine.substr(strlen("Content-Range: bytes"));
result.offset = atoi(tmp.substr(0, tmp.find('-')).c_str());
int ipos = tmp.find('/');
int ivalue = 0;
if (ipos != std::string::npos)
{
ivalue = atoi(tmp.substr(ipos+1).c_str());
}
if (ivalue)
result.total_length = ivalue;
}
strLine.clear();
std::getline(response_stream, strLine);
}
if ( result.http_version.substr(0, 5) != "HTTP/")
{
std::cout << "Invalid response\n";
return false;
}
if (result.status_code != 200 && result.status_code != 206)
{
std::cout << "Response returned with status code "
<< result.status_code << "\n";
return false;
}
packetString.erase(0, nEndHeader + 4);
}
// **************************************************************
// 写入文件
// **************************************************************
{
if (!f_ofsSave.is_open())
{
std::string fn = d_diCurrent->filename;
if (d_diCurrent->continued)
{
fn = d_diCurrent->filename+std::string(".td");
}
{
f_ofsSave.open(fn, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc );
}
if (!f_ofsSave.is_open())
{
return false;
}
d_diCurrent->writesize = 0;
}
try {
f_ofsSave.write(packetString.c_str(), packetString.length());
d_diCurrent->writesize += packetString.length();
}
catch (std::exception &e)
{
return false;
}
}
}
// 关闭文件
f_ofsSave.close();
if (error != boost::asio::error::eof)
throw boost::system::system_error(error);
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
return false;
}
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
return false;
}
return true;
}
// 获取网址对应的IP地址
bool GetHttpIp()
{
try
{
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query("www.csdn.net", "http");
boost::system::error_code e;
tcp::resolver::iterator iter = resolver.resolve(query, e);
tcp::resolver::iterator end;
while (iter != end)
{
tcp::endpoint ep = *iter++;
std::cout<<ep<<std::endl;
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::string szHost ("192.168.1.101");
std::string szParam("/DoDo/aishen.mp4");
GetHttpFile(szHost, szParam);
//GetHttpIp();
system("pause");
return 0;
}
添加boost链接库:
libboost_date_time-vc100-mt-gd-1_53.lib
libboost_regex-vc100-mt-gd-1_53.lib
libboost_system-vc100-mt-gd-1_53.lib