基于原生c++代码实现的Http下载程序
发布日期:2021-09-25 21:40:45 浏览次数:13 分类:技术文章

本文共 5045 字,大约阅读时间需要 16 分钟。

目录


前天用Qt做了一个Http下载工具,但是使用的是Qt的ApI进行开发。所以顺便用纯c++撸了一个,造几个轮子试试效果。

目前基本实现主要功能,但是暂时没有提供断点续传和Https的url下载。只支持对Http的url进行下载。

一、gitHub地址

二、功能

可以输入Http的url进行在线下载。

三、目前存在的问题

暂时没有提供对Https的url下载。

四、界面效果

 

五、主要代码

解析url的ip地址:

void Http::getTcpConfig(const std::string &url){	char domain[100] = { 0 };	char target[100] = { 0 };	char port[10] = { 0 };	char Ip[20] = { 0 };	parseUrl(m_url, domain, target, port);	//解析url	getIp(domain, Ip);		//获取ip	m_ip = Ip;	m_port = port;	m_target = target;	std::cout << "m_ip=" << m_ip << std::endl;	std::cout << "m_port=" << m_port << std::endl;}

 

发出get请求:

void Http::getFileRequest(){	getTcpConfig(m_url);	std::cout << "start request......................." << endl;	if (m_tcp.tcpIsOpen())	//如果是连接状态 关闭重新连接	{		m_tcp.tcpClose();	}	if (!m_tcp.tcpConnect(m_ip, m_port))	{		std::cout << "网络连接失败!" << endl;		return;	}			//接收响应头	char recvBuf[3096] = { 0 };	std::stringstream request;	request << "GET " << m_url << " HTTP/1.1\r\n";	request << "Host: " << m_ip << ":" << m_port << "\r\n";	request << "Connection:close\r\n";	request << "\r\n";	//std::cout << "request = " << request.str().c_str() << std::endl;	//发送请求头	int ret = m_tcp.tcpWrite(request.str().c_str(), sizeof(request));	if (-1 == ret)	{		m_tcp.tcpClose();		return;	}	else if (sizeof(request) == ret)	{		int ret = m_tcp.tcpRead(recvBuf, sizeof(recvBuf));		if (-1 == ret)		{			m_tcp.tcpClose();			return;		}	}	//std::cout << "recvBuf = " << recvBuf << std::endl;	if (std::string(recvBuf).empty())	{		std::cout << "网络异常!"<< std::endl;		return;	}	std::string responStr(recvBuf);	int position = responStr.find("\r\n\r\n");	if (position != -1)	{		position = position + 4;		memset(m_firstBuf, 0, sizeof(m_firstBuf));		m_fRecvByte = 0;		for (int i = position; i < sizeof(recvBuf) / sizeof(char); i++)		{			m_firstBuf[m_fRecvByte++] = recvBuf[i];		}		if (std::string(m_firstBuf).empty())		{			m_fRecvByte = 0;		}	}	//获取返回的状态码	int code = 0;	//返回字符串recvBuf中第一次出现子串HTTP/的地址	char *strPos = strstr(recvBuf, "HTTP/");	if (strPos)	{		sscanf(strPos, "%*s %d", &code);	}	strPos = strstr(recvBuf, "Content-Length");	if (strPos)	{		sscanf(strPos, "%*s %d", &m_fileLength);	}	if (code == 200)	//直接下载	{		downloadFile(m_fileName);	}	else if (code == 302)	//重定向	{		//获取转调地址		strPos = strstr(recvBuf, "Location");		std::string newUrl = std::string(strPos);		int pos = newUrl.find_first_of(":") + 2;		newUrl = newUrl.substr(pos, newUrl.find("\r\n") - pos);		setUrl(newUrl);		getFileRequest();	}	else	{		std::cout << "网络错误 " << code <

进行下载:

void Http::downloadFile(const std::string &m_path){	std::cout << "start download......................." << endl;	if (m_bkptResume)	//是否打开断点续传	{		std::stringstream request;		request << "GET " << m_url << " HTTP/1.1\r\n";		request << "Host:" << m_ip << ":" << m_port << "\r\n";		request << "Range: bytes=" << m_currentDownByte << "-\r\n";		request << "Connection:close\r\n";		request << "\r\n";		//std::cout << "request = " << request.str().c_str() << std::endl;		int ret = m_tcp.tcpWrite(request.str().c_str(), sizeof(request));		if (-1 == ret)		{			m_tcp.tcpClose();			return;		}	}	//创建文件	//FILE *fp = NULL;	//fp = fopen(m_fileName.c_str(), "wb");	m_fileName = m_url.substr(m_url.find_last_of("/") + 1, m_url.size());	m_file.open(m_path, std::ios::out 		| std::ios::trunc | std::ios::binary);	//写入	int bytes = 0;	int total = m_fileLength / (1024 * 1024);	const int wBufLength = 1024 * 1024 * 2;	//2M	//char *writeBuf = (char*)malloc(sizeof(char)*length);	m_writeBuf = new char[wBufLength];	int lastCur = 0;	if (m_fRecvByte != 0)	{		m_file.write(m_firstBuf, m_fRecvByte);		bytes = bytes + m_fRecvByte;	}	while (true)	{		memset(m_writeBuf, 0, wBufLength);		int ret = m_tcp.tcpRead(m_writeBuf, wBufLength);		if (ret == SOCKET_ERROR)		{			std::cout << m_path << "下载错误" << std::endl;			break;		}		else if (ret == 0)		{			std::cout <<"网络中断,请重新下载!" << std::endl;			break;		}		//写入文件		//fwrite(writeBuf, ret, 1, fp);		m_file.write(m_writeBuf, ret);					bytes += ret;		int cur = bytes / (1024);		if (cur == 0)		{			std::cout << cur << "k" << "/" << total << "M" << std::endl;		}		else if (cur != lastCur)		{			lastCur = cur;			std::cout << cur << "k" << "/" << total << "M" << std::endl;		}						if (m_fileLength == bytes)		{			std::cout << m_path << "下载完毕" << std::endl;			break;		}	}	//free(writeBuf);	delete[] m_writeBuf;	m_writeBuf = NULL;	//fclose(fp);	m_tcp.tcpClose();	m_file.close();	}

tcp初始化:

bool Tcp::tcpConnect(const std::string ip, const std::string port){	WORD word = MAKEWORD(2, 2);	WSADATA ws;	if (WSAStartup(word, &ws) != 0)	{		return false;	}	m_sockfd = socket(AF_INET, SOCK_STREAM, 0);	if (m_sockfd == INVALID_SOCKET)	{		perror("m_sockfd:");		return false;	}	memset(&m_clientAddr, 0, sizeof(m_clientAddr));	m_clientAddr.sin_family = AF_INET;	m_clientAddr.sin_port = htons(std::atoi(port.c_str()));	inet_pton(AF_INET, ip.c_str(), &m_clientAddr.sin_addr);	if (INVALID_SOCKET == connect(m_sockfd, (sockaddr*)&m_clientAddr, sizeof(m_clientAddr)))	{		perror("connect:");		return false;	}	std::cout << "connect successful..." << std::endl;	return true;}

 

 

 

转载地址:https://blog.csdn.net/c_shell_python/article/details/106315380 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:std::vector容器
下一篇:Qt实现 Http网络在线下载程序(支持断点续传功能)

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月04日 14时53分05秒