C/C++實(shí)現(xiàn)HTTP協(xié)議解析的示例代碼
超文本傳輸協(xié)議 (HTTP) 是分布式、協(xié)作、超媒體信息系統(tǒng)的應(yīng)用層協(xié)議。 這是自 1990 年以來(lái)萬(wàn)維網(wǎng)數(shù)據(jù)通信的基礎(chǔ)。HTTP 是一種通用且無(wú)狀態(tài)的協(xié)議,它可以用于其他目的,也可以使用其請(qǐng)求方法、錯(cuò)誤代碼和標(biāo)頭的擴(kuò)展。
基本上,HTTP 是一種基于 TCP/IP 的通信協(xié)議,用于通過(guò) Web 傳遞 HTML 文件、圖像文件、查詢(xún)結(jié)果等數(shù)據(jù)。 它為計(jì)算機(jī)之間的通信提供了一種標(biāo)準(zhǔn)化的方式。 HTTP 規(guī)范指定了客戶(hù)端請(qǐng)求的數(shù)據(jù)如何發(fā)送到服務(wù)器,以及服務(wù)器如何響應(yīng)這些請(qǐng)求。
HTTP客戶(hù)端和服務(wù)器通信
客戶(hù)端和服務(wù)器通過(guò)交換單獨(dú)的消息(而不是數(shù)據(jù)流)進(jìn)行通信。 客戶(hù)端(通常是 Web 瀏覽器)發(fā)送的消息稱(chēng)為請(qǐng)求,服務(wù)器發(fā)送的作為應(yīng)答的消息稱(chēng)為響應(yīng)。
HTTP通過(guò) TCP 或 TLS 加密的 TCP 連接發(fā)送的應(yīng)用層協(xié)議,盡管理論上可以使用任何可靠的傳輸協(xié)議。 由于其可擴(kuò)展性,它不僅用于獲取超文本文檔,還用于獲取圖像和視頻或?qū)?nèi)容發(fā)布到服務(wù)器,例如 HTML 表單結(jié)果。 HTTP 還可用于獲取部分文檔以按需更新網(wǎng)頁(yè)。
HTTP和連接
連接是在傳輸層控制的,因此基本上超出了 HTTP 的范圍。 HTTP 不要求底層傳輸協(xié)議是基于連接的;
它只要求它是可靠的,或者不丟失消息。在 Internet 上最常見(jiàn)的兩種傳輸協(xié)議中,TCP 是可靠的,而 UDP 則不是。因此,HTTP 依賴(lài)于基于連接的 TCP 標(biāo)準(zhǔn)。
在客戶(hù)端和服務(wù)器可以交換 HTTP 請(qǐng)求/響應(yīng)對(duì)之前,它們必須建立 TCP 連接,這個(gè)過(guò)程需要多次往返。
HTTP/1.0 的默認(rèn)行為是為每個(gè) HTTP 請(qǐng)求/響應(yīng)對(duì)打開(kāi)一個(gè)單獨(dú)的 TCP 連接。當(dāng)多個(gè)請(qǐng)求連續(xù)發(fā)送時(shí),這比共享單個(gè) TCP 連接效率低。
HTTP 消息
HTTP/1.1 及更早版本中定義的 HTTP 消息是人類(lèi)可讀的。 在 HTTP/2 中,這些消息被嵌入到二進(jìn)制結(jié)構(gòu)中,即一個(gè)幀,允許像壓縮頭和多路復(fù)用這樣的優(yōu)化。 即使在這個(gè)版本的 HTTP 中只發(fā)送原始 HTTP 消息的一部分,每個(gè)消息的語(yǔ)義都不會(huì)改變,客戶(hù)端會(huì)(實(shí)際上)重構(gòu)原始 HTTP/1.1 請(qǐng)求。 因此,理解 HTTP/1.1 格式的對(duì) HTTP/2 消息很有用。
HTTP 消息有兩種類(lèi)型,請(qǐng)求和響應(yīng),每種都有自己的格式。
HTTP請(qǐng)求消息
請(qǐng)求由以下元素組成:
HTTP 方法,通常是 GET、POST 之類(lèi)的動(dòng)詞或 OPTIONS 或 HEAD 之類(lèi)的名詞,用于定義客戶(hù)端想要執(zhí)行的操作。 通常,客戶(hù)端想要獲取資源(使用 GET)或發(fā)布 HTML 表單的值(使用 POST),但在其他情況下可能需要更多操作。
要獲取的資源的路徑; 從上下文中明顯的元素中剝離的資源的 URL。
HTTP響應(yīng)消息
響應(yīng)由以下元素組成:
他們遵循的 HTTP 協(xié)議的版本。
狀態(tài)碼,指示請(qǐng)求是否成功以及原因。
狀態(tài)消息,狀態(tài)代碼的非權(quán)威簡(jiǎn)短描述。
HTTP 標(biāo)頭,例如用于請(qǐng)求的標(biāo)頭。
可選地,包含獲取的資源的主體。
HTTP 狀態(tài)
一些常見(jiàn)的 HTTP 狀態(tài)代碼包括:
200 - 請(qǐng)求成功(網(wǎng)頁(yè)存在)
301 - 永久移動(dòng)(通常轉(zhuǎn)發(fā)到新 URL)
401 - 未經(jīng)授權(quán)的請(qǐng)求(需要授權(quán))
403 - 禁止(不允許訪問(wèn)頁(yè)面或目錄)
500 - 內(nèi)部服務(wù)器錯(cuò)誤(通常由不正確的服務(wù)器配置引起)
HTTP協(xié)議解析及C/C++代碼實(shí)現(xiàn)
... 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; }
運(yùn)行結(jié)果:
總結(jié)
HTTP 是一種易于使用的可擴(kuò)展協(xié)議。 客戶(hù)端-服務(wù)器結(jié)構(gòu)與添加標(biāo)頭的能力相結(jié)合,允許 HTTP 與 Web 的擴(kuò)展功能一起發(fā)展。
盡管 HTTP/2 通過(guò)在幀中嵌入 HTTP 消息來(lái)提高性能增加了一些復(fù)雜性,但消息的基本結(jié)構(gòu)自 HTTP/1.0 以來(lái)一直保持不變。 會(huì)話(huà)流保持簡(jiǎn)單,允許使用簡(jiǎn)單的 HTTP 消息監(jiān)視器對(duì)其進(jìn)行調(diào)查和調(diào)試。
以“http://”開(kāi)頭的 URL 通過(guò)標(biāo)準(zhǔn)超文本傳輸??協(xié)議訪問(wèn),默認(rèn)使用端口 80。以“https://”開(kāi)頭的 URL 通過(guò)安全的 HTTPS 連接訪問(wèn),通常使用端口 443。
以上就是C/C++代碼實(shí)現(xiàn)HTTP協(xié)議解析的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于C++解析HTTP協(xié)議的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
c語(yǔ)言實(shí)現(xiàn)計(jì)算圓周率的近似值
這篇文章主要介紹了c語(yǔ)言實(shí)現(xiàn)計(jì)算圓周率的近似值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12C++實(shí)現(xiàn)日期類(lèi)(Date類(lèi))的方法
下面小編就為大家?guī)?lái)一篇C++實(shí)現(xiàn)日期類(lèi)(Date類(lèi))的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01C語(yǔ)言實(shí)現(xiàn)Linux下的socket文件傳輸實(shí)例
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)Linux下的socket文件傳輸?shù)姆椒?較為詳細(xì)的分析了C語(yǔ)言文件Socket文件傳輸客戶(hù)端與服務(wù)器端相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-06-06C++使用ImGUI框架開(kāi)發(fā)一個(gè)簡(jiǎn)單程序
ImGui?是一個(gè)用于C++的用戶(hù)界面庫(kù),跨平臺(tái)、無(wú)依賴(lài),支持OpenGL、DirectX等多種渲染API,下面就跟隨小編一起學(xué)習(xí)一下如何使用ImGUI框架開(kāi)發(fā)一個(gè)簡(jiǎn)單程序吧2023-08-08C++ VTK實(shí)例之高斯隨機(jī)數(shù)的生成
這篇文章主要介紹了VTK的一個(gè)實(shí)例之高斯隨機(jī)數(shù)的生成,本文演示了從一個(gè)平均數(shù)是0.0和標(biāo)準(zhǔn)偏差是2.2的高斯分布中隨機(jī)生成3個(gè)隨機(jī)數(shù)。感興趣的同學(xué)可以學(xué)習(xí)一下2021-11-11關(guān)于C++類(lèi)的成員初始化列表的相關(guān)問(wèn)題
下面小編就為大家?guī)?lái)一篇關(guān)于C++類(lèi)的成員初始化列表的相關(guān)問(wèn)題。小編覺(jué)得挺2016-05-05VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法
本文主要介紹了VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10