首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++Builder 實作斷點續傳與多線程下載模組(WinInet API)

     編輯:關於C++

下載功能是網路應用的基石。早期單線程下載一旦中斷便須重頭再來;隨著「斷點續傳」與「多線程下載」技術成熟,現代下載器已能大幅提升效率與穩定性。本文基於 C++Builder 5.0 與 WinInet API,詳細闡述支援續傳與多線程的下載模組設計,涵蓋 HTTP 協議基礎、連線建立、檔案資訊查詢、資料讀寫、資源釋放、續傳邏輯、多線程分塊與合併、執行緒同步等核心環節。

一、HTTP 協議與 WinInet API 速覽

下載本質是透過 HTTP GET 向 Web 伺服器請求檔案。WinInet 封裝了 Socket 細節,核心呼叫鏈為:

  1. InternetOpen → 取得會話句柄 hSession
  2. InternetConnect → 取得連線句柄 hConnect
  3. HttpOpenRequest → 取得請求句柄 hRequest(指定 GET、HTTP/1.1、Accept: */*)
  4. HttpSendRequest 發送請求
  5. HttpQueryInfo 取得 Content-Length 等資訊
  6. InternetReadFile 迴圈讀取資料塊
  7. InternetCloseHandle 依序釋放三層句柄

WinInet API 呼叫順序
圖一:WinInet 核心 API 呼叫順序

二、單線程下載執行緒類別 THttpGetThread

繼承 TThread,FreeOnTerminate = true 自動銷毀。關鍵成員:

char Buffer[HTTPGET_BUFFER_MAX+4];
AnsiString FURL, FOutFileName;
HINTERNET FhSession, FhConnect, FhRequest;
bool FSuccess;
int iFileHandle; // 輸出檔案句柄

1. 建立連線 StartHttpGet()

依序呼叫上述 API,try...catch 捕獲失敗並呼叫 EndHttpGet() 釋放資源。

2. 取得檔案大小 GetWEBFileSize()

HttpQueryInfo(HTTP_QUERY_CONTENT_LENGTH) 解析 Content-Length 標頭,觸發 DoOnGetFileSize 事件供上層分塊使用。

3. 開啟輸出檔案 OpenOutFile()

若檔案已存在則刪除重建,回傳 FileCreate 句柄。

4. 執行下載迴圈 DoHttpGet()

while (true) {
    Application->ProcessMessages();
    bool ReadReturn = InternetReadFile(FhRequest, Buffer, dwRequest, &dwRead);
    if (!ReadReturn || dwRead == 0) break;
    Buffer[dwRead] = '\0';
    FileWrite(iFileHandle, Buffer, dwRead);
    dwCount += dwRead;
    DoOnProgress(dwCount); // 進度回呼
}

5. 釋放資源 EndHttpGet()

逆序 InternetCloseHandle,並將句柄變數歸零。

6. 執行緒入口 Execute()

包含重試迴圈(預設 5 次),成功觸發 OnComplete,失敗觸發 OnError。

三、斷點續傳實作

核心兩步:

  1. 本地檢查:OpenOutFile 中若檔案存在,取其大小作為已下載位移,FileSeek(handle, 0, 2) 移至檔尾準備續寫。
  2. 伺服器支援檢查:DoHttpGet 開頭呼叫 InternetSetFilePointer(或 HTTP Range 標頭)將伺服器檔案指標移至續傳位置;若伺服器不支援(SetFilePointer 失敗),則刪除本地檔案重頭下載。

四、多線程下載架構 THttpGetEx

元件化設計,動態建立/銷毀執行緒陣列。

1. 執行緒擴充屬性

int FIndex;           // 陣列索引
DWORD dwStart;        // 起始位移
DWORD dwTotal;        // 需下載位元組數
DWORD FGetBytes;      // 實際下載量

DoHttpGet 迴圈中依 dwTotal 修正讀取長度與結束條件。

2. 資源分配與分塊策略 CreateHttpThreads()

  • 先建立一個暫時執行緒取得 FileSize
  • 平均分塊:AvgSize = FileSize / ThreadCount,最後一塊補齊餘數
  • 用最後一塊測試伺服器是否支援 SetFilePointer(CanMulti)
  • 不支援則退回單線程;支援則建立完整執行緒陣列,各自指定 StartPostion、GetBytes、獨立暫存檔 OutTmpFiles[i]

3. 啟動下載 DownLoadFile()

遍歷陣列呼叫 Resume() 啟動所有執行緒。

4. 完成同步與檔案合併 OnThreadComplete

建立命名互斥體 http-get-thread-mutex 確保同一時間僅有一個執行緒進入合併邏輯:

FSuccesss[Index] = true;
bool allDone = true;
for (int i=0; i

五、實務考量

  • 網路波動處理:Execute 中的重試機制可擴充為指數退避
  • 異步 I/O:InternetOpen 指定 INTERNET_FLAG_ASYNC 並配合回呼函數,可避免阻塞 UI 執行緒
  • 大檔案支援:使用 64 位元位移(LARGE_INTEGER)突破 2GB 限制
  • 進度顯示:主執行緒透過 Synchronize 或訊息佇列更新 UI

六、總結

本文提供一套可直接落地的 C++Builder 下載模組原始碼架構,涵蓋從單線程基礎到多線程分塊、續傳邏輯、執行緒同步與檔案合併的完整鏈路。開發者可據此擴充支援 HTTPS、Proxy、限速、校驗等進階功能,打造生產級下載元件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved