日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

http 断点续传,Windows下HTTP方式单线程下载

發布時間:2023/12/18 windows 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 http 断点续传,Windows下HTTP方式单线程下载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http 斷點續傳
www.diybl.com??? 時間 : 2011-05-20? 作者:匿名?? 編輯:hawk 點擊:? 1128 [ 評論 ]
-
-
???


原理:
1. 打開本地文件fopen,移動文件指針到文件尾fseek
2. 獲得文件大小ftell, 格式化HTTP請求頭 "Range: bytes=ftell -", 以偏移httpfile指針,實現斷點續傳
3. 獲得要下載的文件,以二進制形式傳輸,OpenURL
4. 接收數據,防止阻塞PeekMessage?
Sample:

顯示代碼打印
01 char string[25];???

02? CString StrFileName=m_lf;???

03? CString StrUrl=m_url;???

04? CString sheader;??

05? long lStartPos =0;??

06?????

07? //打開本地文件,m_lf 是文件路徑,如:C:\\a.mp3??

08? FILE *file=NULL;??

09? file=fopen(m_lf,"ab");??

10? if(file!=NULL)??

11? {??

12? //移動文件指針到文件尾??

13?? fseek(file,0,SEEK_END);??

14?? lStartPos=ftell(file);??

15?? itoa(lStartPos,string,10);??

16?? m_byte=string;??

17? //格式化請求頭,如: 從第 1000 個字節起開始下載:“Range: bytes=999 -”??

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 *hf=NULL;??

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 nReadSize=0;???

35?? nReadSize=hf->Read(nbytes,512);???

36?? while( nReadSize >0)???

37?? {???

38??? fwrite(nbytes,1,nReadSize,file);???

39??? nReadSize=hf->Read(nbytes,512);???

40??? lStartPos=ftell(file);??

41??? itoa(lStartPos,string,10);??

42??? m_byte=string;??

43 //防止阻塞??

44??? doenents();??

45?? }???

46?????

47?? fclose(file);??

48?? hf->Close();??

49?? delete hf;??

50? }??

51? }catch(CInternetException *p){??

52 //? hf=NULL;??

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", pHostEnd+1);

??? //根據HOST信息獲得對應的IP和端口
??? char *pPortStart = strchr(pHostInf, '':'');
??? if (!pPortStart)
??? {
??????? *Port = 80;??? //默認為80
??? }
??? else
??? {
??????? *pPortStart = ''\0'';
??????? sscanf(pPortStart+1, "%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(RecvBuf+strlen("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

總結

以上是生活随笔為你收集整理的http 断点续传,Windows下HTTP方式单线程下载的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。