在開始介紹具體程式模組之前,我們先系統性地回顧一下 WinPcap 開發網路嗅探器的完整核心流程。掌握這些基礎步驟,對於後續的 MFC 介面整合與模組設計至關重要。
使用 pcap_findalldevs_ex() 函數枚舉本機所有可用的網路介面卡。該函數返回一個 pcap_if 結構體的鏈結串列,每個節點包含一張網卡的詳細資訊(名稱、描述、IP 位址等)。
/* 獲取本地機器設備列表 */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
fprintf(stderr, "Error in pcap_findalldevs_ex: %s\\n", errbuf);
exit(1);
}
呼叫 pcap_open() 開啟指定網卡,建立封包捕獲會話。關鍵參數包括:snaplen(最大捕獲長度,通常設 65536 保證完整封包)、flags(設為 PCAP_OPENFLAG_PROMISCUOUS 啟用混雜模式)、to_ms(讀取逾時,毫秒單位)。
/* 打開設備 */
if ((adhandle = pcap_open(d->name, 65536, PCAP_OPENFLAG_PROMISCUOUS,
1000, NULL, errbuf)) == NULL) {
fprintf(stderr, "\\nUnable to open the adapter. %s\\n", d->name);
pcap_freealldevs(alldevs);
return -1;
}
使用 pcap_compile() 將高階布林運算式(如 "ip and tcp")編譯為底層位元碼,再以 pcap_setfilter() 綁定至捕獲會話。只有符合條件的封包才會被複製給應用程式。
/* 編譯並設定過濾器 */
if (pcap_compile(adhandle, &fcode, "ip and tcp", 1, netmask) < 0) {
fprintf(stderr, "\\nUnable to compile the packet filter.\\n");
pcap_freealldevs(alldevs);
return -1;
}
if (pcap_setfilter(adhandle, &fcode) < 0) {
fprintf(stderr, "\\nError setting the filter.\\n");
pcap_freealldevs(alldevs);
return -1;
}
主要有兩種模式:
pcap_loop() 基於回呼函數處理封包,適合單執行緒簡單應用。pcap_next_ex() 逐個獲取封包,回傳值含義:1(成功)、0(逾時)、-1(錯誤)、-2(離線檔案讀取結束)。多執行緒 C++ 程式建議採用此模式,避免回呼增加複雜度。int res = pcap_next_ex(adhandle, &header, &pkt_data);
取得封包資料後,需依據協定結構(以太網標頭、IP 標頭、TCP/UDP 標頭等)進行解析,提取來源/目的 IP、埠號、旗標、承載資料等資訊,並可在 MFC 介面(如 ListCtrl、TreeCtrl)即時顯示。
程式結束前務必呼叫 pcap_freealldevs() 釋放裝置列表記憶體,關閉捕獲控制代碼,避免資源洩漏。
void pcap_freealldevs(pcap_if_t **alldevs);

下一節將進入實戰:MFC+WinPcap 編寫嗅探器之四(獲取模組實作),敬請期待。