营销网站建设方案,wordpress门户,铁岭 网站建设,wordpress 公开显示为http 断点续传www.diybl.com 时间 #xff1a; 2011-05-20 作者#xff1a;匿名 编辑#xff1a;hawk 点击#xff1a; 1128 [ 评论 ]-- 原理#xff1a; 1. 打开本地文件fopen#xff0c;移动文件指针到文件尾fseek 2. 获得文件大小ftell, 格式化HTTP请求头 2011-05-20 作者匿名 编辑hawk 点击 1128 [ 评论 ]-- 原理 1. 打开本地文件fopen移动文件指针到文件尾fseek 2. 获得文件大小ftell, 格式化HTTP请求头 Range: bytesftell -, 以偏移httpfile指针实现断点续传 3. 获得要下载的文件以二进制形式传输OpenURL 4. 接收数据防止阻塞PeekMessage Sample: 显示代码打印01 char string[25]; 02 CString StrFileNamem_lf; 03 CString StrUrlm_url; 04 CString sheader; 05 long lStartPos 0; 06 07 //打开本地文件m_lf 是文件路径如C:\\a.mp3 08 FILE *fileNULL; 09 filefopen(m_lf,ab); 10 if(file!NULL) 11 { 12 //移动文件指针到文件尾 13 fseek(file,0,SEEK_END); 14 lStartPosftell(file); 15 itoa(lStartPos,string,10); 16 m_bytestring; 17 //格式化请求头如 从第 1000 个字节起开始下载“Range: bytes999 -” 18 sheader.Format(_T(%sRange: bytes%d-\r\n), szHeaders,lStartPos); 19 } 20 else 21 { 22 MessageBox(local file failed!); 23 return; 24 } 25 try{ 26 CInternetSession s; 27 CHttpFile *hfNULL; 28 //获得要下载的文件以二进制形式传输 29 hf(CHttpFile*)s.OpenURL(m_url,1,INTERNET_FLAG_TRANSFER_BINARY,sheader,-1 ); 30 if(hf!NULL) 31 { 32 //开始传输数据 33 byte *nbytes new byte[512]; 34 int nReadSize0; 35 nReadSizehf-Read(nbytes,512); 36 while( nReadSize 0) 37 { 38 fwrite(nbytes,1,nReadSize,file); 39 nReadSizehf-Read(nbytes,512); 40 lStartPosftell(file); 41 itoa(lStartPos,string,10); 42 m_bytestring; 43 //防止阻塞 44 doenents(); 45 } 46 47 fclose(file); 48 hf-Close(); 49 delete hf; 50 } 51 }catch(CInternetException *p){ 52 // hfNULL; 53 p-Delete(); 54 } 55 BOOL CGfDlg::doenents() 56 { 57 MSG msg; 58 while(::PeekMessage(msg,NULL,0,0,PM_NOREMOVE)) 59 { 60 if(!AfxGetApp()-PumpMessage()) 61 { 62 ::PostQuitMessage(0); 63 return false; 64 } 65 } 66 return true; 67 } 文章出处飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/c/cppjs/20090409/164681.html 但是因为当时用了CFile类实现而不是SDK所以我不得不重写重写时断点续传又重新成了问题 1.下载的是文件列表2.因为效率不再采用分块传输3.如何记录文件列表与断点值 鉴于我以前做的断点续传思路被禁固了一样 转不开弯 直到后来KING老大提示才饶过这个弯 其思路如下 1.客户端用CreateFile以OPEN_EXISTING方式打开要下载的文件列表2.若成功说明有断点文件,则用GetFileSize得到大小做为断点3若失败说明文件不存在,则创建一个文件 思路是相当简单的而且一个好处是不用记录断点值 干净利落文章出处飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/c/cppjs/2007114/83747.html 源码 Windows下HTTP方式单线程下载www.diybl.com 时间 2008-03-31 作者佚名 编辑本站 点击 509 [ 评论 ]-- 针对昨天的试验结果书写了一个HTTP方式单线程下载的小程序目前尚不支持断点续传。希望各位看客使劲拍砖 原理套接字发送HTTP GET方式的请求然后根据HTTP响应循环接收信息。 #include stdio.h#include stdlib.h#include string.h#include WinSock2.h#include windows.h#include HttpDown.h #pragma comment(lib, Ws2_32.lib) /************************************************************************//* 全局变量 *//************************************************************************/unsigned long g_FiltTotleLen 0; //下载文件总大小unsigned long g_DownedFileLen 0; //已下载文件大小 /************************************************************************//* 函数描述判断某一指定字符串是否为ip地址 *//* 返回值 是则返回0,否则返回-1 *//* 作者 liuwp *//* 创建时间2008-03-27 *//* 其他 *//************************************************************************/int IsIpAddrV4Str(char *pstr){ char a[4],b[4],c[4],d[4]; int num 0; if ( !pstr) return -1; num sscanf(pstr,%3[0-9].%3[0-9].%3[0-9].%3[0-9],a,b,c,d); if ( num ! 4 ) return -1; if ( atoi(a)255 || atoi(b)255 || atoi(c) 255 || atoi(d) 255 ) return -1; return 0;} /************************************************************************//* 函数描述根据下载地址获得HOST、IP等信息 *//* 返回值 成功返回0失败返回1 *//* 作者 liuwp *//* 创建时间2008-03-27 *//* 其他 *//************************************************************************/int GetDownInfoByUlr(const char *pDownUrl, char *pIpAddr, int *Port , char *pGetInfo, int GetLen, char *RetErrorBuf, int ErrorLen){ int RetCode 0; char pUrlTempBuf[1000]; char pHostInf[500]; memset(pUrlTempBuf, 0, sizeof(pUrlTempBuf)); memset(pHostInf, 0, sizeof(pHostInf)); //参数判断 if (!pDownUrl || !pIpAddr || !Port || !pGetInfo || !RetErrorBuf) return -1; //拷贝字符串 strncpy(pUrlTempBuf, pDownUrl, sizeof(pUrlTempBuf)-1); //获得HOST起始位置 char *pHostStart strstr(pUrlTempBuf, ://); if (!pHostStart) { _snprintf(RetErrorBuf, ErrorLen-1, 给定的下载URL格式错误应该类似 http://HOST/GET ); return -1; } //根据第一个 “/”获得HOST信息 pHostStart pHostStart strlen(://); char *pHostEnd strchr(pHostStart, /); if (!pHostEnd) { _snprintf(RetErrorBuf, ErrorLen-1, 给定的下载URL格式错误应该类似 http://HOST/GET ); return -1; } *pHostEnd \0; _snprintf(pHostInf, sizeof(pHostInf)-1, %s, pHostStart); //获得GET信息 _snprintf(pGetInfo, GetLen-1, /%s, pHostEnd1); //根据HOST信息获得对应的IP和端口 char *pPortStart strchr(pHostInf, :); if (!pPortStart) { *Port 80; //默认为80 } else { *pPortStart \0; sscanf(pPortStart1, %d, Port); } //判断获得地址是否为IP,不是则转换为IP RetCode IsIpAddrV4Str(pHostInf); if (RetCode ! 0) { //初始化环境 WSADATA WSAData; WSAStartup(MAKEWORD(2,2),WSAData); struct hostent* lpHostEnt gethostbyname(pHostInf); if(lpHostEnt NULL) { _snprintf(RetErrorBuf, ErrorLen-1, 获得域名对应的IP地址失败, GetLastError()%d, GetLastError()); return -1; } else { LPSTR lpaddr lpHostEnt-h_addr_list[0]; if(lpaddr) { struct in_addr inAddr; memcpy (inAddr, lpaddr, 4); sprintf(pIpAddr, %s, inet_ntoa (inAddr) ); } } //清除环境 WSACleanup(); } else { sprintf(pIpAddr, %s, pHostInf ); } return 0;} /************************************************************************//* 函数描述通过HTTP协议进行下载 *//* 返回值 下载成功返回0失败返回1 *//* 作者 liuwp *//* 创建时间2008-03-27 *//* 其他 *//************************************************************************/int DownByHttpFun(const char *pDownUrl, const char *pDownFile, unsigned long *pTotleLen , char *RetErrorBuf, int ErrorLen){ WSADATA WSAData; sockaddr_in ServerAddr; fd_set fdset; struct timeval tv; HANDLE hFileHandle NULL; bool FirstFlag true; int RetCode 0; int WriteLen 0; char SendBuf[1000]; char RecvBuf[4096]; char IpAddr[30]; char GetInfo[600]; int Port 0; char *pConLen NULL; DWORD dwFileSize 0; memset(IpAddr, 0, sizeof(IpAddr)); memset(GetInfo, 0, sizeof(GetInfo)); memset(RecvBuf, 0, sizeof(RecvBuf)); memset(SendBuf, 0, sizeof(SendBuf)); if (!pDownUrl || !pDownFile || !pTotleLen || !RetErrorBuf) { _snprintf(RetErrorBuf, ErrorLen-1, 给定参数不正确); return -1; } //根据下载地址获得HOST, GET, IP端口等信息 RetCode GetDownInfoByUlr(pDownUrl, IpAddr, Port , GetInfo, sizeof(GetInfo)-1, RetErrorBuf, ErrorLen); if (RetCode ! 0) return -1; //初始化环境 WSAStartup(MAKEWORD(2,2),WSAData); //创建套接字 SOCKET Sock socket(AF_INET, SOCK_STREAM, 0); if ( SOCKET_ERROR Sock ) { _snprintf(RetErrorBuf, ErrorLen-1, 创建套接字失败, GetLastError() %d !, GetLastError()); goto LEXIT; } //给定服务器地址 ServerAddr.sin_family AF_INET; ServerAddr.sin_addr.s_addr inet_addr(IpAddr); ServerAddr.sin_port htons(Port); //连接服务器 RetCode connect(Sock, (struct sockaddr *)ServerAddr, sizeof(ServerAddr)); if (RetCode SOCKET_ERROR) { _snprintf(RetErrorBuf, ErrorLen-1, 连接服务器失败, GetLastError() %d !, GetLastError()); goto LEXIT; } //发送信息 _snprintf(SendBuf, sizeof(SendBuf)-1 , GET %s HTTP/1.1\r\nHost: %s:%d\r\n\r\n ,GetInfo, IpAddr, Port); RetCode send(Sock, SendBuf, strlen(SendBuf), 0); if (RetCode 0) { _snprintf(RetErrorBuf, ErrorLen-1, 发送数据失败, GetLastError() %d !, GetLastError()); closesocket(Sock); WSACleanup(); goto LEXIT; } //接收信息 FD_ZERO(fdset); FD_SET(Sock, fdset); tv.tv_sec 2*60; //秒 tv.tv_usec 0; //打开文件 hFileHandle CreateFile(pDownFile, GENERIC_WRITE, 0 , (LPSECURITY_ATTRIBUTES) NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL); if (hFileHandle INVALID_HANDLE_VALUE) { _snprintf(RetErrorBuf, ErrorLen-1, 打开文件%s失败, GetLastError() %d ! , pDownFile, GetLastError()); goto LEXIT; } //置空全局变量 g_FiltTotleLen 0; //下载文件总大小 g_DownedFileLen 0; //已下载文件大小 while(1) { memset(RecvBuf, 0, sizeof(RecvBuf)); int len select(0, fdset, NULL, NULL, tv); if (len 1) { break; } //套接字接收信息 len recv(Sock, RecvBuf, sizeof(RecvBuf)-1 ,0); if (len 0) { break; } if (!FirstFlag) //不是第一次追加写 { dwFileSize GetFileSize(hFileHandle, NULL); SetFilePointer(hFileHandle, dwFileSize, NULL, FILE_BEGIN); RetCode WriteFile(hFileHandle, RecvBuf, len , (DWORD*)WriteLen, NULL); if (RetCode 0) { _snprintf(RetErrorBuf, ErrorLen-1, 写入文件失败 ! GetLastError() %d !, GetLastError()); goto LEXIT; } //获得此时已经下载的文件大小 g_DownedFileLen dwFileSize len; //如果已经下载完毕则跳出 if (g_DownedFileLen *pTotleLen) break; continue; } //判断返回值 int RetCode 0; sscanf(RecvBufstrlen(HTTP/1.1 ), %d, RetCode); if (RetCode 200 || RetCode 300) { _snprintf(RetErrorBuf, ErrorLen-1, 下载失败, 服务器返回码为%d !, RetCode); goto LEXIT; } //获得总大小 pConLen strstr(RecvBuf, \r\nContent-Length:); if (!pConLen) { _snprintf(RetErrorBuf, ErrorLen-1, HTTP协议中未给定文件的大小!); goto LEXIT; } sscanf(pConLen, \r\nContent-Length: %ld\r\n, pTotleLen); g_FiltTotleLen *pTotleLen; char *pEnd strstr(RecvBuf, \r\n\r\n); if (!pEnd) { break; } pEnd pEnd strlen(\r\n\r\n); //移动到文件尾部,写文件 dwFileSize GetFileSize(hFileHandle, NULL); SetFilePointer(hFileHandle, dwFileSize, NULL, FILE_BEGIN); RetCode WriteFile(hFileHandle, pEnd, len-(pEnd-RecvBuf) , (DWORD*)WriteLen, NULL); if (RetCode 0) { _snprintf(RetErrorBuf, ErrorLen-1, 写入文件失败 ! GetLastError() %d !, GetLastError()); goto LEXIT; } //获得此时已经下载的文件大小 g_DownedFileLen dwFileSize len - (pEnd - RecvBuf); //更改第一次接收标识 FirstFlag false; } //下载完毕,判断下载大小是否相同 dwFileSize GetFileSize(hFileHandle, NULL); if (pTotleLen *pTotleLen ! 0 *pTotleLen ! dwFileSize) { _snprintf(RetErrorBuf, ErrorLen-1, 下载文件不完整, 请重新下载!); goto LEXIT; } //关闭文件 if (hFileHandle) { CloseHandle(hFileHandle); hFileHandle NULL; } //关闭套接字 if (Sock ! 0) { closesocket(Sock); Sock 0; } //清除环境 WSACleanup(); return 0; LEXIT: //关闭文件 if (hFileHandle) { CloseHandle(hFileHandle); hFileHandle NULL; } //关闭套接字 if (Sock ! 0) { closesocket(Sock); Sock 0; } //清除环境 WSACleanup(); return -1; } /************************************************************************//* 函数描述获得文件下载的相关信息 *//* 返回值 *//* 作者 liuwp *//* 创建时间2008-03-28 *//* 其他 *//************************************************************************/float GetDownloadRate(unsigned long *pTotleLen , unsigned long *pDownLen){ float DownRate 0; if (!pTotleLen || !pTotleLen ) return 0; //获得文件总大小和已下载的大小 *pTotleLen g_FiltTotleLen; *pDownLen g_DownedFileLen; //计算速率 if (g_FiltTotleLen 0) return 0; if (g_DownedFileLen 0) return 0; DownRate (float)g_DownedFileLen/(float)g_FiltTotleLen; return DownRate;} 文章出处飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/c/cppjs/2008331/107753.html 转载于:https://www.cnblogs.com/Ray-chen/archive/2011/12/14/2287959.html