首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

使用 C 語言實現指定端口 HTTP 請求抓取並寫入文件的思路

     編輯:程式設計綜合問答

需求分析

目標:監聽指定端口(如 80)上的所有 HTTP 請求數據包,將請求內容(特別是 GET 請求)寫入文本文件。純用戶態 C 代碼實現,不依賴 libpcap 等第三方庫。

技術難點

  • 原始套接字權限:創建 SOCK_RAW 需 Root/Administrator 權限。
  • TCP 流重組:HTTP 基於 TCP 流,數據包可能分片、亂序、重傳,單純抓取 IP 包無法直接得到完整 HTTP 請求,需實現 TCP 狀態機重組流。
  • 內核協議棧競爭:系統內核已處理 TCP 連接,用戶態 Raw Socket 收到的包是副本,無法直接「攔截」已建立連接的數據,除非繞過內核(如 DPDK、XDP)。

可行方案對比

| 方案 | 實現難度 | 權限需求 | 適用場景 | |------|----------|----------|----------| | **Raw Socket + TCP 重組** | 極高 (需寫微型 TCP 協議棧) | Root | 教學/研究 | | **libpcap / WinPcap / Npcap** | 低 (成熟 API) | Root/Admin | 生產抓包分析 | | **iptables NFQUEUE + 用戶態處理** | 中 (需內核模塊配合) | Root | 透明代理/防火牆 | | **eBPF / XDP (Linux 4.18+)** | 中高 (需內核支持) | Root | 高性能內核級過濾 | | **應用層代理 / 中間件** | 低 (Nginx/Go/Java 幾行代碼) | 普通用戶 | **最推薦** |

推薦方案:應用層代理 (最工程化)

不要在 C 語言底層造輪子。在應用層攔截:

  1. 配置 Nginx/Envoy 作為反向代理,啟用 access_log 記錄完整請求體。
  2. 或編寫簡單 Go/Java/Python HTTP Server 轉發請求並記錄日誌。
  3. 若必須 C 語言:使用 libevent/libuv + http-parser 寫一個高性能 HTTP 代理/服務器,幾百行代碼即可穩定運行。

若堅持 Raw Socket 思路(僅供學習)

// 伪代碼流程
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
// 綁定網卡 (可選)
struct sockaddr_in sin = { .sin_family = AF_INET, .sin_port = htons(80) };
bind(sock, (struct sockaddr*)&sin, sizeof(sin));

while (1) {
    char buf[65536];
    int len = recv(sock, buf, sizeof(buf), 0);
    // 1. 解析 IP 頭 -> 獲取源/目標 IP、協議
    // 2. 解析 TCP 頭 -> 獲取源/目標端口、SEQ/ACK、標誌位、數據偏移
    // 3. 提取 Payload
    // 4. **關鍵**:維護一個哈希表 (四元組 -> TCP 會話狀態),按 SEQ 重組流
    // 5. 解析重組後的 HTTP 協議 (請求行、頭、體)
    // 6. 寫入文件
}

總結

「少量 C 代碼實現」是不現實的。工程上請使用 成熟的抓包庫 (libpcap/Npcap) 或 應用層代理/日誌。若為學習網絡協議,建議從 libpcap 循環抓包開始,逐步理解 TCP 重組邏輯。

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