C/C++實現HTTP協議解析的示例代碼
超文本傳輸協議 (HTTP) 是分佈式、協作、超媒體信息系統的應用層協議。 這是自 1990 年以來萬維網數據通信的基礎。HTTP 是一種通用且無狀態的協議,它可以用於其他目的,也可以使用其請求方法、錯誤代碼和標頭的擴展。
基本上,HTTP 是一種基於 TCP/IP 的通信協議,用於通過 Web 傳遞 HTML 文件、圖像文件、查詢結果等數據。 它為計算機之間的通信提供瞭一種標準化的方式。 HTTP 規范指定瞭客戶端請求的數據如何發送到服務器,以及服務器如何響應這些請求。
HTTP客戶端和服務器通信
客戶端和服務器通過交換單獨的消息(而不是數據流)進行通信。 客戶端(通常是 Web 瀏覽器)發送的消息稱為請求,服務器發送的作為應答的消息稱為響應。
HTTP通過 TCP 或 TLS 加密的 TCP 連接發送的應用層協議,盡管理論上可以使用任何可靠的傳輸協議。 由於其可擴展性,它不僅用於獲取超文本文檔,還用於獲取圖像和視頻或將內容發佈到服務器,例如 HTML 表單結果。 HTTP 還可用於獲取部分文檔以按需更新網頁。
HTTP和連接
連接是在傳輸層控制的,因此基本上超出瞭 HTTP 的范圍。 HTTP 不要求底層傳輸協議是基於連接的;
它隻要求它是可靠的,或者不丟失消息。在 Internet 上最常見的兩種傳輸協議中,TCP 是可靠的,而 UDP 則不是。因此,HTTP 依賴於基於連接的 TCP 標準。
在客戶端和服務器可以交換 HTTP 請求/響應對之前,它們必須建立 TCP 連接,這個過程需要多次往返。
HTTP/1.0 的默認行為是為每個 HTTP 請求/響應對打開一個單獨的 TCP 連接。當多個請求連續發送時,這比共享單個 TCP 連接效率低。
HTTP 消息
HTTP/1.1 及更早版本中定義的 HTTP 消息是人類可讀的。 在 HTTP/2 中,這些消息被嵌入到二進制結構中,即一個幀,允許像壓縮頭和多路復用這樣的優化。 即使在這個版本的 HTTP 中隻發送原始 HTTP 消息的一部分,每個消息的語義都不會改變,客戶端會(實際上)重構原始 HTTP/1.1 請求。 因此,理解 HTTP/1.1 格式的對 HTTP/2 消息很有用。
HTTP 消息有兩種類型,請求和響應,每種都有自己的格式。
HTTP請求消息
請求由以下元素組成:
HTTP 方法,通常是 GET、POST 之類的動詞或 OPTIONS 或 HEAD 之類的名詞,用於定義客戶端想要執行的操作。 通常,客戶端想要獲取資源(使用 GET)或發佈 HTML 表單的值(使用 POST),但在其他情況下可能需要更多操作。
要獲取的資源的路徑; 從上下文中明顯的元素中剝離的資源的 URL。
HTTP響應消息
響應由以下元素組成:
他們遵循的 HTTP 協議的版本。
狀態碼,指示請求是否成功以及原因。
狀態消息,狀態代碼的非權威簡短描述。
HTTP 標頭,例如用於請求的標頭。
可選地,包含獲取的資源的主體。
HTTP 狀態
一些常見的 HTTP 狀態代碼包括:
200 – 請求成功(網頁存在)
301 – 永久移動(通常轉發到新 URL)
401 – 未經授權的請求(需要授權)
403 – 禁止(不允許訪問頁面或目錄)
500 – 內部服務器錯誤(通常由不正確的服務器配置引起)
HTTP協議解析及C/C++代碼實現
... void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { ... /* print source and destination IP addresses */ printf(" From: %s\n", inet_ntoa(ip->ip_src)); printf(" To: %s\n", inet_ntoa(ip->ip_dst)); /* determine protocol */ switch(ip->ip_p) { case IPPROTO_TCP: printf(" Protocol: TCP\n"); break; case IPPROTO_UDP: printf(" Protocol: UDP\n"); break; case IPPROTO_ICMP: printf(" Protocol: ICMP\n"); return; case IPPROTO_IP: printf(" Protocol: IP\n"); return; default: printf(" Protocol: unknown\n"); return; } /* * OK, this packet is TCP. */ /* define/compute tcp header offset */ if(ip->ip_p == IPPROTO_TCP) { ... printf(" Src port: %d\n", ntohs(tcp->th_sport)); printf(" Dst port: %d\n", ntohs(tcp->th_dport)); int sport = ntohs(tcp->th_sport); int dport = ntohs(tcp->th_dport); ... if (size_payload > 0) { printf(" Payload (%d bytes):\n", size_payload); //print_payload(payload, size_payload); if ((sport == 80) || (dport == 80)) { printf(" HTTP prase:\n"); prase_http(payload, size_payload); } else if(sport == 443 || dport == 443) { printf(" SSL/TLS prase:\n"); prase_ssl_tls(payload, size_payload); } } } ... } int main(int argc, char *argv[]) { char errbuf[100]; pcap_t *desc = 0; char *filename = argv[1]; if (argc != 2) { printf("usage: ./dissect_http [pcap file]\n"); return -1; } printf("ProcessFile: process file: %s\n", filename); if ((desc = pcap_open_offline(filename, errbuf)) == NULL) { printf("pcap_open_offline: %s error!\n", filename); return -1; } pcap_loop(desc, -1, got_packet, NULL); pcap_close(desc); return 0; }
運行結果:
總結
HTTP 是一種易於使用的可擴展協議。 客戶端-服務器結構與添加標頭的能力相結合,允許 HTTP 與 Web 的擴展功能一起發展。
盡管 HTTP/2 通過在幀中嵌入 HTTP 消息來提高性能增加瞭一些復雜性,但消息的基本結構自 HTTP/1.0 以來一直保持不變。 會話流保持簡單,允許使用簡單的 HTTP 消息監視器對其進行調查和調試。
以“http://”開頭的 URL 通過標準超文本傳輸協議訪問,默認使用端口 80。以“https://”開頭的 URL 通過安全的 HTTPS 連接訪問,通常使用端口 443。
以上就是C/C++代碼實現HTTP協議解析的示例代碼的詳細內容,更多關於C++解析HTTP協議的資料請關註WalkonNet其它相關文章!