
上一篇的簡易客戶端存在三大短板:僅支持 IP 直連、硬編碼單一 URL、單次 recv 截斷長響應。本文實現通用網頁刷新器,解決這三問題:
gethostbyname() 解析recv() 直到對端關閉,完整接收響應#include <comlib.h> // 假設項目通用庫
// HTTP GET 請求模板(雙 %s 分別佔位 路徑、Host)
char req_tmpl[] =
"GET %s HTTP/1.0\r\n"
"Accept: */*\r\n"
"Accept-Language: zh-cn\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\n"
"Host: %s\r\n"
"Connection: Keep-Alive\r\n\r\n";
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return 1;
}
char *host = argv[1]; // 如 www.example.com
char *path = argv[2]; // 如 /vote.asp?id=1001
// 1. 域名解析
struct hostent *he = gethostbyname(host);
if (!he) { herror("gethostbyname"); return 2; }
char *ip = inet_ntoa(*(struct in_addr*)he->h_addr);
fprintf(stderr, "Resolved IP: %s\n", ip);
// 2. 建立 TCP 連接(端口 80)
int sock;
ASSERT(ConnectSock(&sock, 80, ip) == 0); // 假設通用庫封裝
// 3. 組裝並發送請求
char req[2048];
sprintf(req, req_tmpl, path, host); // 關鍵:格式化字符串可為變量
WriteFile(sock, req, strlen(req));
fprintf(stderr, ">>> Request sent:\n%s", req);
// 4. 循環完整接收響應
char buf[1024];
int total = 0, n;
while ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
fwrite(buf, 1, n, stderr); // 直接輸出到 stderr 觀察
total += n;
}
fprintf(stderr, "\n<<< Total received: %d bytes\n", total);
close(sock);
return 0;
}
# 編譯(鏈接自定義 comlib)
cc -o http2 http2.c -O -DUNIX -DDEBUG -DTRACE_FILE='"./trace"' \
-I/u/zyx/code/comlib/include -L/u/zyx/code/comlib/lib -lcom
# 實戰 1:新浪遊戲投票(模擬瀏覽器投票)
./http2 publish.games.sina.com.cn "/poll.php?p_id=560&t_id=1327"
# 實戰 2:訪問任意網站首頁
./http2 www.csai.cn /
sprintf(buf, buf2, argv[2], argv[1]) 中 buf2 是變量而非字面量,C 標準完全支持,極大提升模板復用靈活性。
HTTP/1.0 默認 Connection: Close,服務器發送完數據主動關閉連接,客戶端 recv 返回 0 表示接收結束。對於 Keep-Alive 或 Chunked 編碼,需解析 Content-Length 或分塊結束標記。
gethostbyname 失敗 → herror 輸出詳細 DNS 錯誤ConnectSock 斷言失敗 → 終止程序recv 返回 -1 → 檢查 errno 區分中斷/超時/連接重置本工具僅供學習 Socket 編程、HTTP 協議、域名解析之用。 請勿用於壓力測試、惡意刷流量、暴力破解等違法行為。任何對目標服務器造成損害的使用均與作者無關,使用者自負法律責任。
Content-Length、Set-Cookie、Location 等關鍵信息http_get(host, path, headers, timeout, &resp) 供其他模塊調用掌握這個刷新器核心模型,你已具備開發爬蟲、API 客戶端、監控探針、自動化測試工具的基因。