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

從零手寫 Linux 多線程 HTTP 服務器:核心架構、CGI 機制與代碼全解析

     編輯:關於C語言

項目背景與目標

本文詳細記錄一個基於 Linux C 語言、採用多線程 + 多進程 CGI 架構的簡易 HTTP 服務器(httpd)開發過程。涵蓋 Socket 網絡編程、pthread 線程池、fork/exec 進程管理、管道通信、HTTP 協議解析等核心技術,適合作為網絡編程入門實戰項目。

整體架構設計

  • httpd.c:核心服務器,監聽端口,多線程接受連接,解析 HTTP 請求,區分靜態文件與 CGI 動態請求。
  • client.c:簡易測試客戶端,發送 GET 請求驗證服務器。
  • index.html:測試靜態頁面。
  • Makefile:自動化編譯鏈接。

核心模塊深度解析

1. 線程模型:主線程 accept + 工作線程分離屬性

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 循環 accept,創建分離線程處理每個客戶端
pthread_create(&tid, &attr, request_accept, (void*)cfd);

分離屬性避免線程退出時殭屍佔用資源,無需主動 join。

2. HTTP 請求解析流程

  1. 讀取請求行(getfdline 處理 \r\n)
  2. 解析 Method(GET/POST)、Path、Query String
  3. 統一讀取並丟棄 Header 直到空行
  4. 根據文件屬性決定:可執行 → CGI,否則 → 靜態文件

3. CGI 執行機制:雙管道 + fork/exec

pipe(pocgi); // 子進程 stdout → 父進程讀取
pipe(picgi); // 父進程寫入 → 子進程 stdin
if (fork() == 0) { // 子進程
    dup2(pocgi[1], STDOUT_FILENO);
    dup2(picgi[0], STDIN_FILENO);
    putenv("REQUEST_METHOD=GET/POST");
    putenv("QUERY_STRING=..."); // 或 CONTENT_LENGTH
    execl(path, path, NULL);
}
// 父進程:寫 POST 數據到 picgi[1],從 pocgi[0] 讀取輸出發送給客戶端

環境變量傳遞參數,符合 CGI/1.1 規範。

4. 響應碼封裝

內聯函數 response_200/400/404/500/501 統一發送 HTTP 頭部與簡易 HTML 體,提高代碼複用性。

編譯與測試

# Makefile
all: httpd.out client.out
httpd.out: httpd.c
    gcc -g -Wall -o $@ $^ -lpthread
client.out: client.c
    gcc -g -Wall -o $@ $^

啟動服務器後會隨機分配端口(避免 8080 衝突),客戶端需指定該端口測試。

關鍵技術點總結

  • 非阻塞/阻塞 Socket 選擇與 MSG_PEEK 讀取技巧
  • strcasecmp 跨平台替代方案(str_icmp)
  • 指針運算優於下標訪問的性能本質(a[i] ≡ *(a+i))
  • 管道文件描述符 0 讀 1 寫的約定與 dup2 重定向
  • 隨機端口綁定:port=0 讓內核分配,再用 getsockname 獲取

項目地址與擴展方向

完整源碼打包:CSDN 下載
參考項目:Tinyhttpd
後續可嘗試:非阻塞 I/O + epoll、HTTPS 支持、WebSocket、配置文件解析、日誌系統等。

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