WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) return FALSE;
// ... 使用 socket ...
WSACleanup();
BOOL HttpClient(LPCTSTR serverIp, int port, LPCTSTR path, LPCTSTR saveFile) {
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET) return FALSE;
sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(serverIp);
if (connect(s, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
closesocket(s); return FALSE;
}
// 建構 HTTP GET 請求
CStringA request;
request.Format("GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n", path, serverIp);
if (send(s, request, request.GetLength(), 0) == SOCKET_ERROR) {
closesocket(s); return FALSE;
}
// 接收回應並寫檔
FILE* fp = fopen(saveFile, "wb");
if (!fp) { closesocket(s); return FALSE; }
char buf[4096];
int nRecv;
while ((nRecv = recv(s, buf, sizeof(buf), 0)) > 0) {
fwrite(buf, 1, nRecv, fp);
}
fclose(fp);
closesocket(s);
return TRUE;
}
HttpTestIDC_BTN_GET 處理:void CHttpTestDlg::OnBtnGet() {
CString strIp = _T("168.160.224.185"); // 電腦世界日報
CString strPath = _T("/99/tips/");
CString strFile = _T("index.htm");
if (HttpClient(strIp, 80, strPath, strFile)) {
AfxMessageBox(_T("下載完成,已儲存為 index.htm"));
ShellExecute(m_hWnd, _T("open"), strFile, NULL, NULL, SW_SHOW); // 瀏覽器開啟
} else {
AfxMessageBox(_T("下載失敗,請檢查網路/伺服器"));
}
}
| 項目 | 說明 |
|---|---|
| HTTP/1.0 vs 1.1 | 1.0 預設 Connection: close,適合簡易客戶端;1.1 需處理 Chunked 編碼、Keep-Alive |
| Host 標頭 | HTTP/1.1 強制要求,虛擬主機必要 |
| 回應解析 | 狀態行 → 標頭 (雙 CRLF 分隔) → 實體內容;需處理 Content-Length、Transfer-Encoding: chunked |
| 重導向 (301/302) | 需解析 Location 標頭,重新發起請求 |
| HTTPS | 需 SSL/TLS 層 (OpenSSL/Schannel),非純 Socket 可完成 |
WSAAsyncSelect 或 WSAEventSelect 進行事件驅動Range: bytes=start-end 標頭同樣 Socket 架構,僅更換命令字串:
| 協議 | Port | 命令範例 |
|---|---|---|
| SMTP | 25 | HELO / MAIL FROM / RCPT TO / DATA |
| POP3 | 110 | USER / PASS / LIST / RETR / QUIT |
| FTP | 21 | USER / PASS / PASV / RETR / STOR |
| Telnet | 23 | 協商選項 / 字元流互動 |
| TIME | 37 | 無命令,連線即回傳 32-bit 秒數 (NTP 前身) |
send/recv 可能部分發送/接收,生產代碼必須迴圈處理直到完成recv 返回 0 表示對端正常關閉 (EOF);SOCKET_ERROR 表示錯誤WSAEWOULDBLOCK,配合 select/WSAEventSelectWSAStartup 版本協商結果,確保支援 2.2掌握 socket → connect → send(HTTP GET) → recv 迴圈 核心模式,即可輕鬆實作各類 TCP 協議客戶端,奠定網路程式設計堅實基礎。