本文詳細記錄一個基於 Linux C 語言、採用多線程 + 多進程 CGI 架構的簡易 HTTP 服務器(httpd)開發過程。涵蓋 Socket 網絡編程、pthread 線程池、fork/exec 進程管理、管道通信、HTTP 協議解析等核心技術,適合作為網絡編程入門實戰項目。
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。
getfdline 處理 \r\n)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 規範。
內聯函數 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 衝突),客戶端需指定該端口測試。
MSG_PEEK 讀取技巧strcasecmp 跨平台替代方案(str_icmp)a[i] ≡ *(a+i))dup2 重定向port=0 讓內核分配,再用 getsockname 獲取完整源碼打包:CSDN 下載
參考項目:Tinyhttpd
後續可嘗試:非阻塞 I/O + epoll、HTTPS 支持、WebSocket、配置文件解析、日誌系統等。