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

基於 select I/O 模型的遠程目錄瀏覽與多線程斷點下載

     編輯:關於VC++

本專案實作一個「遠程檔案管理 + 多線程下載」系統:伺服端採用 select 模型單線程處理大量連線;客戶端主線程負責 UI 與目錄樹互動,下載時動態建立多執行緒分段傳輸,支援斷點續傳邏輯。

架構概覽

  • 伺服端:一個 select 執行緒輪詢 fd_set(預設 64 sockets),新連線 accept 加入集合,資料到達 recv 解析封包並回應。
  • 客戶端:主線程維護目錄樹(雙擊展開懶加載),下載請求啟動多線程,各線程負責連續區段寫入同一檔案(需鎖同步)。

核心資料結構

// 通訊封包
struct DATA_PACKET {
    char packetType;        // 'r':驅動器 'd':目錄 'f':檔案大小 'D':檔案資料
    unsigned int length;    // 依類型語意不同(下載時:高兩位=線程序號,低兩位=總線程數)
    char content[2000];     // 路徑或資料
};

// 全域變數(線程間通訊)
char* pDrives;              // 緩衝區
CString arrFiles[200];      // 目錄列表
CString savePath;           // 儲存路徑
long fSize=0, recvFSize=0;  // 檔案總大小/已收大小
CString strIP;              // 伺服 IP
bool thrFlag=false;         // 線程建立同步旗標

關鍵技術難點與解法

1. MFC Socket vs Win32 API

CAsyncSocket 跨線程傳遞參數極不便,改用純 Win32 socket/select/send/recv 靈活度高;檔案操作保留 CFile 或 fopen/fwrite。

2. 字串陣列跨 Socket 傳輸

直接 send 結構體含 CString 陣列會導致接收端指標失效。解法:將陣列序列化為單一 char*,以特殊字元 '|' 分隔(檔名不含此字元),接收端再解析還原。

3. 多線程建立競態條件

迴圈 CreateThread 時,若主線程繼續跑,迴圈變數 j 可能已變更導致子線程拿到錯誤參數。
解法:while(CreateThread(...)==0) Sleep(30); 或用 thrFlag 置位機制——子線程啟動成功置 1,主線程等待歸零後再建下一個。

4. 多線程同步寫入同一檔案

  • 每線程計算負責區段:start = (idx-1)*len; end = (idx==total)? fSize : start+len;
  • 寫入前 fseek 定位,寫入後 fflush 強制落盤。
  • 用 CCriticalSection 鎖住「定位+寫入+fflush」最小關鍵區,避免效能過度下降。
  • 最後完成的線程負責 fclose。

5. 雙層迴圈解析緩衝區邊界檢查

while (i <= len && j <= 6) {
    int k = 0;
    while (pChar[i] != '|' && i <= len) { // 必須加 i<=len
        strArray[j].Insert(k++, pChar[i++]);
    }
    i++; j++;
}

6. memcpy 緩衝區預分配陷阱

全域 char[2000] 二次 memcpy 若未重新分配,程式結束時會崩潰。解法:每次使用前 new char[2000] 或 memset 重置。

核心函式流程圖解

  • 伺服端 Select 執行緒:FD_ZERO/SET → select → FD_ISSET → accept/recv → 解析封包類型 → 回應
  • 客戶端下載線程 FillInFile:計算區段 → 迴圈 recv+fseek+fwrite+fflush → 完成判斷 fclose
  • 客戶端請求線程 ThreadRequest:連線 → send請求 → recv回應 → 分派處理(驅動器/目錄/檔案大小/檔案資料) → 呼叫 FillInFile

目錄樹互動邏輯

自訂 CExtnTreeCtrl 繼承 CTreeCtrl,雙擊項目:
① 驅動器/資料夾 → 送 'd' 封包請求子項 → 回應填充樹節點。
② 檔案(有副檔名) → 送 'f' 取大小 → 彈出參數對話框設定線程數/路徑 → 送 'D' 多線程下載。

此架構在區域網路環境下表現穩定,可作為 FTP/HTTP 多線程下載器的 Socket 層參考實作。

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