基于原生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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月04日 14时53分05秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Unity Shader 入门精要(01) -- 渲染流水线
2019-04-26
Unity Shader 入门精要(02) -- shader的编码基础
2019-04-26
Unity Shader 入门精要(03) -- Unity的基础光照
2019-04-26
Unity Shader 入门精要(04) -- 基础纹理
2019-04-26
Unity3D 移动平台的资源路径问题
2019-04-26
二分查找(折半查找)
2019-04-26
线段树
2019-04-26
编程机制
2019-04-26
自己写的Java版计算器
2019-04-26
字、位、字节摘抄的,怕忘了
2019-04-26
printf与scanf的用法知识(C Primer Plus总结)
2019-04-26
三目运算符(条件运算符)
2019-04-26
C语言中的goto语句
2019-04-26
欧几里德算法及拓展
2019-04-26
CSDN-markdown编辑器基本用法
2019-04-26
等差数列公式搜集
2019-04-26
复合字面量(compound literal)
2019-04-26
gets和puts
2019-04-26
fgets、gets_s和fputs
2019-04-26
解决centos7联网问题
2019-04-26