linux c++下载http文件并显示进度<转>
来源:互联网 发布:c语言标准库函数源码 编辑:程序博客网 时间:2024/05/17 23:38
#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 = 0, // starting position for searches skip = 1; // 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 == 0) 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=-1; 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[1024*1024] = {0}; 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, 0)) == -1) { 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,0,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(80); servaddr.sin_family = AF_INET; //make the connection if(connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) { error->append("Couldn't connect!"); return size; } write(sock_id,request.c_str(),request.length()); //read the response msglen = read(sock_id,message,1024*1024); headersize= msglen; info.append(message,0,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==-1) { 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[18000] = {0}; char messagetop[18000]={0}; int msglen; float readcount=0; 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, 0)) == -1) { return; } //book uses bzero which my man pages say is deprecated //the man page said to use memset instead. :-) memset(&servaddr,0,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(80); servaddr.sin_family = AF_INET; //make the connection if(connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) { 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,18000); if(msglen==0) break; if(readcount==0) { int tempindex=0; for(int i =hsize-1;i<msglen;i++) { messagetop[tempindex]= message[i]; tempindex=tempindex+1; } outfile.write (messagetop,tempindex); } else { outfile.write (message,msglen); } readcount=readcount+msglen; progress=readcount/size*100; }while(readcount<=(size+ hsize)); outfile.close(); close(sock_id); //read the response}float filesize;int loadprogress=0;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,0); while(loadprogress<99) { printf("Progress %d \n", loadprogress); usleep(1000000); } return 0;}
在使用该代码测试的时候可能会出现的问题:
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 操作。待以后再测一测看看。
0 0
- linux c++下载http文件并显示进度<转>
- libcurl 通过http协议下载文件并显示下载进度
- C++Builder利用URLDownloadToFile下载文件并显示进度
- NSURLConnection下载文件并显示进度
- NSURLConnection下载文件并显示进度(HEAD)
- NSURLConnection下载文件并显示进度(HEAD)
- Unity下载文件并显示进度
- Unity3d下载大型文件并显示进度
- 常用C头文件 <c...>
- AsyncTask下载网络文件,并显示下载进度
- Groovy下载文件并实时显示下载进度
- android中如何下载文件并显示下载进度
- android中如何下载文件并显示下载进度
- C#下载文件并显示显示进度的方法实现
- Symbian中Http下载文件引擎,支持进度显示
- Android 下载网络url文件并显示进度
- 文件下载之使用AsyncTask并在进度对话框中显示下载进度
- <转>C 语言总复习
- 游戏中按概率播放某个音效简单c++实现
- string转int 等(转)
- MFC-Dialog各函数的执行顺序
- Linux下类似windows下_beginthread和_endthread 的多线程开发
- SAP系统参数设置
- linux c++下载http文件并显示进度<转>
- 言必信,行必果,硁硁然小人哉!
- c++实现一个比较两个string类型的版本号的小demo
- Android 解压zip文件(支持中文)
- Eclipse 工程使用相对路径导入Jar包设置
- android中配置文件property的用途以及使用<转>
- PocketSphinx语音识别系统的编程
- NDK开发中的一个HTTP下载实例附带下载进度
- OpenSL ES 查询设备支持的SL Profiles