#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <fstream>
#include <vector>
#include <pthread.h>
using namespace std;
typedef string::size_type (string::*find_t)(const string& delim,
string::size_type offset) const;
vector<string> Split(const string& s,
const string& match,
bool removeEmpty=false,
bool fullMatch=false)
{
vector<string> result; // return container for tokens
string::size_type start = , // starting position for searches
skip = ; // positions to skip after a match
find_t pfind = &string::find_first_of; // search algorithm for matches
if (fullMatch)
{
skip = match.length();
pfind = &string::find;
}
while (start != string::npos)
{
string::size_type end = (s.*pfind)(match, start);
if (skip == ) end = string::npos;
string token = s.substr(start, end - start);
if (!(removeEmpty && token.empty()))
{
result.push_back(token);
}
if ((start = end) != string::npos) start += skip;
}
return result;
}
void SplitProperty(vector<string> property,string* name,string *value)
{
vector<string>::iterator it=property.begin();
if(it!= property.end())
{
name->clear();
name->append(*it);
}
it++;
if(it!= property.end())
{
value->clear();
value->append(*it);
}
}
int GetFileSize(char* host,char* file,string* error,int& headersize)
{
int size=-;
struct sockaddr_in servaddr;
struct hostent *hp;
string splitline="\r\n";
string PName;
string PValue;
string splittagbalue=":";
string info;
vector<string> properties;
vector<string> property;
int sock_id;
char message[*] = {};
int msglen;
string request;
request.append("HEAD ");
request.append(file);
request.append(" HTTP/1.1\n");
request.append("Host:");
request.append(host);
request.append("\r\n\r\n");
//Get a socket
if((sock_id = socket(AF_INET, SOCK_STREAM, )) == -) {
error->append("Couldn't get a socket!");
return size;
}
//book uses bzero which my man pages say is deprecated
//the man page said to use memset instead. :-)
memset(&servaddr,,sizeof(servaddr));
//get address for google.com
if((hp = gethostbyname(host)) == NULL) {
error->append("Couldn't access network.");
error->append(host);
return size;
}
//bcopy is deprecated also, using memcpy instead
memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length);
//fill int port number and type
servaddr.sin_port = htons();
servaddr.sin_family = AF_INET;
//make the connection
if(connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) != ) {
error->append("Couldn't connect!");
return size;
}
write(sock_id,request.c_str(),request.length());
//read the response
msglen = read(sock_id,message,*);
headersize= msglen;
info.append(message,,msglen);
close(sock_id);
properties =Split(info,splitline,true);
vector<string>::iterator it;
for (it=properties.begin(); it<properties.end(); it++)
{
property= Split(*it,splittagbalue,true);
SplitProperty(property,&PName,&PValue);
if(PName=="Content-Length")
{
size =atoi(PValue.c_str());
break;
}
}
if(size==-)
{
error->append("Resource Not Found!");
}
return size;
}
void DownloadFile(char* host,char* file,char * savefile,float size,int& progress,int hsize)
{
struct sockaddr_in servaddr;
struct hostent *hp;
string info;
int sock_id;
char message[] = {};
char messagetop[]={};
int msglen;
float readcount=;
string request;
request.append("GET ");
request.append(file);
request.append(" HTTP/1.1\n");
request.append("Host:");
request.append(host);
request.append("\r\n\r\n");
//Get a socket
if((sock_id = socket(AF_INET, SOCK_STREAM, )) == -) {
return;
}
//book uses bzero which my man pages say is deprecated
//the man page said to use memset instead. :-)
memset(&servaddr,,sizeof(servaddr));
//get address for google.com
if((hp = gethostbyname(host)) == NULL) {
return;
}
//bcopy is deprecated also, using memcpy instead
memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length);
//fill int port number and type
servaddr.sin_port = htons();
servaddr.sin_family = AF_INET;
//make the connection
if(connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) != ) {
return;
}
//NOW THE HTTP PART!!!
//send the request
write(sock_id,request.c_str(),request.length());
ofstream outfile (savefile,ofstream::binary);
do{
msglen = read(sock_id,message,);
if(msglen==)
break;
if(readcount==)
{
int tempindex=;
for(int i =hsize-;i<msglen;i++)
{
messagetop[tempindex]= message[i];
tempindex=tempindex+;
}
outfile.write (messagetop,tempindex);
}
else
{
outfile.write (message,msglen);
}
readcount=readcount+msglen;
progress=readcount/size*;
}while(readcount<=(size+ hsize));
outfile.close();
close(sock_id);
//read the response
}
float filesize;
int loadprogress=;
int hsize;
pthread_t tUpdateWork;
void* UpdateWorCoping(void* data)
{
DownloadFile("192.168.2.128","/games.data","/usr/games.data",filesize,loadprogress,hsize);
}
int main(int argc, char** argv)
{
string error;
filesize = GetFileSize("192.168.2.128","/games.data",&error,hsize);
pthread_create(&tUpdateWork,NULL,UpdateWorCoping,);
while(loadprogress<)
{
printf("Progress %d \n", loadprogress);
usleep();
}
return ;
}

在使用该代码测试的时候可能会出现的问题:

1.

在DownloadFile 内的有两处:

 char message[18000] = {0};
 char messagetop[18000]={0};
可能在运行的时候造成栈溢出,所以最好是修改为动态申请空间。
另外还有一处就是GetFileSize() 内 问题同上。

2.

在DownloadFile() 内的写文件中:

里面有个for循环:for(int i = hsize -1; i<msglen ; i++)

我在亲自测试的发现 hsize - 1 会使文件保存大小跟原始文件有出入。于是暂时改成了 for(int i = hsize ; i<msglen ; i++)

不知道对于其他类型文件是否应该 做 -1 操作。待以后再测一测看看。

linux c++下载http文件并显示进度<转>的更多相关文章

  1. 实现在 .net 中使用 HttpClient 下载文件时显示进度

    在 .net framework 中,要实现下载文件并显示进度的话,最简单的做法是使用 WebClient 类.订阅 DownloadProgressChanged 事件就行了. 但是很可惜,WebC ...

  2. 使用libcurl开源库和Duilib做的下载文件并显示进度条的小工具

    转载:http://blog.csdn.net/mfcing/article/details/43603525 转载:http://blog.csdn.net/infoworld/article/de ...

  3. C# WinFrom 导入Excel文件,显示进度条

    因为WINForm程序是在64位上运行如果使用另外一种快速的读取Excel的方法会报“未在本地计算机上注册“Microsoft.Jet.OLEDB.12.0”提供程序” 所以我就换了现在这种读取有点慢 ...

  4. 从Linux服务器下载网站文件

    最近公司迁来一个新客户,该客户的网站是别的网络服务商做的,放在linux主机上,因为客户跟之前的网络服务商合作的不愉快 所以就把网站迁到我们公司,经理让我把网站文件和数据库download下来并在我们 ...

  5. C# Winform下载文件并显示进度条

    private void btnDown_Click(object sender, EventArgs e) { DownloadFile("http://localhost:1928/We ...

  6. Winform下载文件并显示进度条

    本来是要研究怎样判断下载完成,结果找到这个方法,可以在这个方法完成之后提示下载完成. 代码如下: using System; using System.Collections.Generic; usi ...

  7. 通过HttpUrlConnection下载文件并显示进度条

    实现效果: 核心下载块: int count = 0; URL url = new URL("http://hezuo.downxunlei.com/xunlei_hezuo/thunder ...

  8. [c#]WebClient异步下载文件并显示进度

    摘要 在项目开发中经常会用到下载文件,这里使用winform实现了一个带进度条的例子. 一个例子 using System; using System.Collections.Generic; usi ...

  9. ajax 上传文件,显示进度条,进度条100%,进度条隐藏,出现卡顿就隐藏进度条,显示正在加载,再显示上传完成

    <form id="uploadForm" method="post" enctype="multipart/form-data"&g ...

随机推荐

  1. k最邻近算法——使用kNN进行手写识别

    上篇文章中提到了使用pillow对手写文字进行预处理,本文介绍如何使用kNN算法对文字进行识别. 基本概念 k最邻近算法(k-Nearest Neighbor, KNN),是机器学习分类算法中最简单的 ...

  2. 【转】每天一个linux命令(26):用SecureCRT来上传和下载文件

    原文网址:http://www.cnblogs.com/peida/archive/2012/11/28/2793181.html 用SSH管理linux服务器时经常需要远程与本地之间交互文件.而直接 ...

  3. vuex、redux、mobx 对比

    出处:https://www.w3cplus.com/javascript/talk-about-front-end-state-management.html 其实大部分概念都差不多,只不过VUEX ...

  4. Spring MVC 向页面传值-Map、Model、ModelMap、ModelAndView

    Spring MVC 向页面传值,有4种方式: ModelAndView Map Model ModelMap 使用后面3种方式,都是在方法参数中,指定一个该类型的参数. Model Model 是一 ...

  5. logging 的配置和使用

    logging 的配置和使用 reference : logging cookbook logging HOWTO 测试源码,example import logging nt = 'xwei' # ...

  6. iText使用经历

    最近用iText搞了下PDF,虽然一路趟坑而过,毕竟是搞出来了,所以iText还是不错的开源PDF生成软件的.先看搞出来的PDF长啥样: 然后看一路趟过来的坑: 1.表格怎么生成,具体是行怎么生成?列 ...

  7. Linux中CPU亲和性(go)

    http://www.cnblogs.com/LubinLew/p/cpu_affinity.html

  8. platform device和platform driver简述

    首先我们在module_init中使用platform_driver_register来注册我们的驱动.一般来说platform_driver_register放在module_init的最后调用,因 ...

  9. C/C++基础----string, vector, array

    1 using声明 方便使用命名空间中的成员,不用每次xxx::yyy 头文件不应该包含using声明(不经意间包含了一些名字) 2 string 表3.1:初始化string对象的方式 string ...

  10. session 、cookie、token的区别

    session session的中文翻译是“会话”,当用户打开某个web应用时,便与web服务器产生一次session.服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后sess ...