[計算機網絡]httpserver--如何解析HTTP請求報文

這個http server的實現源代碼我放在了我的github上,有興趣的話可以點擊查看哦。

在上一篇文章中,講述了如何編寫一個最簡單的server,但該程序只是接受到請求之后馬上返回響應,實在不能更簡單。在正常的開發中,應該根據不同的請求做出不同的響應。要做到上述的功能,首先要解析客戶端發來的請求報文。

報文在不同的上下文情景下有不同的理解,本文所說的報文都是在HTTP上下文中描述的名詞。

HTTP報文是什么

在HTTP程序中,報文就是HTTP用來搬運東西的包裹,也可以理解為程序之間傳遞信息時發送的數據塊。這些數據塊以一些文本形式的元信息開頭,這些信息描述了報文的內容和含義,后面跟著可選的數據部分。

報文的流動

HTTP使用屬于流入和流出來描述報文的傳遞方向。HTTP報文會像合水一樣流動。不管時請求報文還是響應報文,都會向下游流動,所有報文的發送者都在接受者的上游。下圖展示了報文向下游流動的例子。

報文向下游流動

報文的組成

報文由三個部分組成:

  • 對報文進行描述的起始行

  • 包含屬性的首部塊

  • 可選的、包含數據的主體部分

起始行和首部是由行分隔的ASCII文本。每行都以一個由兩個字符(回車符--ASCII碼13和換行符--ASCII碼10)組成的行終止序列結束。可以寫做CRLF

盡管規范說明應該用CRLF來表示行終止,但穩健的應用程序也應該接受單個換行作為行的終止。筆者僅支持以CRLF換行的解析,因為我覺得既然有了規范,那就需要遵循,遵循相同的協議的程序才能互相通信。

實體是一個可選的數據塊。與起始行和首部不同的是,主體中可以包含主體或二進制數據,也可以為空(比如僅僅GET一個頁面或文件)。

下面來看看報文的語法的格式和規則。

報文的語法

請求報文的語法:

<method> <request-URL> <version>
<headers><entity-body>

響應報文的語法:

<version> <status-code> <reason-phrase>
<headers><entity-body>

method,方法

客戶端希望服務器對資源執行的操作。比如GET、POST

request-URL,請求URL

請求資源,或者URL路徑組件的完整URL。

version,版本

報文所使用的HTTP版本。格式:HTTP/<major>.<minor>。其中major(主要版本號)和minor(次要版本號)都是整數。

status-code,狀態碼

描述請求過程所發生的情況的數字。

reason-phrase,原因短語

數字狀態碼的文字描述版本。

headers,首部

每個首部包含一個名字,后面跟著一個冒號(:),然后是一個可選的空格,接著是一個值,最后是一個CRLF。可以有零個或多個首部。首部由一個CRLF結束,表示首部結束和實體主體開始。

entity-body,實體的主體部分

包含一個由任意數據組成的數據塊。可以沒有,此時是以一個CRLF結束。

請求行

請求報文的起始行稱為請求行。所有的HTTP報文都以一行起始行作為開始。請求行包含一個方法和一個請求URL以及HTTP的版本三個字段。每個字段都以空格分隔。

比如:GET / HTTP/1.1

請求方法為GET,請求URL為/,HTTP版本為HTTP/1.1。

響應行

響應報文的起始行稱為響應行。響應行包含HTTP版本、數字狀態碼以及描述操作狀態的文本形式的原因短語。三個字段也是以空格分隔。

比如:HTTP/1.1 200 OK

HTTP版本為HTTP/1.1,數字狀態碼是200,原因短語是OK。表示請求成功。

首部

首部是是包含在請求和響應報文的一些附加信息。本質上,他們只是一些鍵值對的列表。

比如:Content-Length: 19

表示返回內容長度為19。

實體的主體部分

簡單地說,這部分就是HTTP要傳輸的內容。

解析請求報文

了解了報文是如何組成和各部分代表的內容之后,就對如何解析請求報文心里有數了。

核心代碼

    /* 解析請求行 */int parse_start_line(int sockfd, char *recv_buf, req_pack *rp){char *p = recv_buf;char *ch = p;int i = 0;enum parts { method, url, ver } req_part = method;char *method_str;char *url_str;char *ver_str;int k = 0;if (*ch < 'A' || *ch > 'Z') {return -1;}while (*ch != CR) {if (*ch != BLANK) {k++;} else if (req_part == method) {method_str = (char *)malloc(k * sizeof(char *));memset(method_str, 0, sizeof(char *));strncpy(method_str, recv_buf, k);k = 0;req_part = url;} else if (req_part == url) {url_str = (char *)malloc(k * sizeof(char *));memset(url_str, 0, sizeof(char *));strncpy(url_str, recv_buf + strlen(method_str) + 1, k);k = 0;req_part = ver;}ch++;i++;}if (req_part == url) {if (k != 0) {url_str = (char *)malloc(k * sizeof(char));memset(url_str, 0, sizeof(char));strncpy(url_str, recv_buf + strlen(method_str) + 1, k);k = 0;} else {return -1;}}if (k == 0) {ver_str = (char *)malloc(8 * sizeof(char));memset(ver_str, 0, sizeof(char));strcpy(ver_str, "HTTP/1.1");} else {ver_str = (char *)malloc(k * sizeof(char));memset(ver_str, 0, sizeof(char));strncpy(ver_str,recv_buf + strlen(method_str) + strlen(url_str) + 2, k);}rp->method = method_str;rp->url = url_str;rp->version = ver_str;return (i + 2);}/* 解析首部字段 */int parse_header(int sockfd, char *recv_buf, header headers[]){char *p = recv_buf;char *ch = p;int i = 0;int k = 0;int v = 0;int h_i = 0;bool is_newline = false;char *key_str;char *value_str;header *tmp_header = (header *)malloc(sizeof(header *));memset(tmp_header, 0, sizeof(header));while (1) {if (*ch == CR && *(ch + 1) == LF) {break;}while (*ch != COLON) {ch++;i++;k++;}if (*ch == COLON) {key_str = (char *)malloc(k * sizeof(char *));memset(key_str, 0, sizeof(char *));strncpy(key_str, recv_buf + i - k, k);k = 0;ch++;i++;}while (*ch != CR) {ch++;i++;v++;}if (*ch == CR) {value_str = (char *)malloc(v * sizeof(char *));memset(value_str, 0, sizeof(char *));strncpy(value_str, recv_buf + i - v, v);v = 0;i++;ch++;}i++;ch++;headers[h_i].key = key_str;headers[h_i].value = value_str;h_i++;}return (i + 2);}

解析思想

遍歷recv接受到的請求字符串,檢查是否遇到回車符r判斷一行數據。

對于起始行,檢查是否遇到空格分隔不同的字段;對于首部,檢查是否遇到冒號分隔鍵值對的字段值;對于實體的主體部分,則先判斷是否遇到CRLF字符串,然后將剩余內容全部作為實體的主體部分。

返回值是告知程序下一次遍歷的起始位置。

如果遇到非法請求行則返回400的響應。

總結

解析報文的過程就是遵循HTTP協議規定的內容去解析報文,獲取報文包含的信息。

由于基礎知識較薄弱,代碼還有很多錯誤以及很多地方需要優化。如果有看到錯誤的地方或有其它建議望各位大俠不吝賜教。^_^

這個http server的實現源代碼我放在了我的github上,有興趣的話可以點擊查看哦。

原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。

如果本文對你有幫助,請點下推薦吧,謝謝^_^

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/542291.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/542291.shtml
英文地址,請注明出處:http://en.pswp.cn/news/542291.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python字典副本_如何復制字典并僅在Python中編輯副本?

python字典副本Python never implicitly copies the dictionary or any objects. So, while we set dict2 dict1, were making them refer to the same dictionary object. Hence, even when we mutate the dictionary, all the references made to it, keep referring to the…

英特爾核芯顯卡控制面板沒有了_核顯和獨顯、集成顯卡有什么區別

集成顯卡&#xff1a;一般不帶有顯存&#xff0c;而是使用系統的一部分主內bai存作為顯存&#xff0c;具體的數量一般是系統根據需要自動動態調整的。顯然&#xff0c;如果使用集成顯卡運行需要大量占用內存的空間&#xff0c;對整個系統的影響會比較明顯&#xff0c;此外系統內…

徐州初中計算機學校排名2015,徐州初中學校排名,徐州重點初中排名詳細榜單

2018年徐州初中學校排名,徐州重點初中排名詳細榜單孩子小升初&#xff0c;幾乎所有的家長都會陷入糾結&#xff0c;都想為孩子選擇一所“好學校”&#xff0c;在擇校過程中&#xff0c;家長們總想知道徐州初中學校排名以及徐州重點初中排名詳細榜單&#xff0c;但這里小編提醒一…

分布式計算 MapReduce與yarn工作機制

一、第一代hadoop組成與結構第一代Hadoop&#xff0c;由分布式存儲系統HDFS和分布式計算框架MapReduce組成&#xff0c;其中&#xff0c;HDFS由一個NameNode和多個DataNode組成&#xff0c;MapReduce由一個JobTracker和多個TaskTracker組成&#xff0c;對應Hadoop版本為Hadoop …

c++ stl隊列初始化_創建一個向量,并將其像C ++ STL中的數組一樣初始化

c stl隊列初始化向量是什么&#xff1f; (What is the vector?) Vector is a container in C STL, it is used to represent array and its size can be changed. Vector是C STL中的一個容器&#xff0c;用于表示數組&#xff0c;并且其大小可以更改。 Read more: C STL Vec…

計算機無法上無線網絡連接到internet,電腦連接不上無線網絡,教您怎么解決電腦連接不上無線網絡...

小編家的那位筆記本姐姐之前可能是受委屈了&#xff0c;一個一個的電腦問題丟出來給我解決。之前有段時間總是出現電腦連接不上無線網絡的問題&#xff0c;弄得那短時間天天都在想辦法是解決。現在&#xff0c;我就要將這種解決方法分享給你們&#xff0c;讓你們在遇到這個問題…

格蘭杰因果關系檢驗_混頻(mixed frequency)數據的格蘭杰因果(Grange causality)檢驗及其Matlab實現...

格蘭杰和格蘭杰因果網絡搜到的Grange大神標準照格蘭杰1934年9月出生于英國威爾士的斯旺西&#xff0c;早期就讀于諾丁漢大學&#xff0c;接受當時英國第一個經濟學數學雙學位教育&#xff0c;1955年留校任教&#xff0c;1957年在天文學雜志上他發表了第一篇論文&#xff1a;“關…

C#Convert.ToInt32(byte)方法-將字節值轉換為int

C&#xff03;Convert.ToInt32(byte)方法 (C# Convert.ToInt32(byte) Method) Convert.ToInt32(byte) Method is used to convert a specific byte value to its equivalent integer (int 32 signed number). Convert.ToInt32(byte)方法用于將特定的字節值轉換為其等效的整數(i…

后臺窗口截圖_萬人擁捧的截圖軟件來啦!讓你的工作效率提升不止一倍!

文章來自微信公眾號&#xff1a;小七有料直接進入正題&#xff0c;今天不野給大家分享兩款截圖軟件——Snipaste和FastStone Capture&#xff0c;前者與其說是一個截圖軟件&#xff0c;我更愿意稱之為貼圖軟件。兩者都在工作中很大程度提高了我的效率&#xff0c;也簡便化了我很…

ibm nvidia 超級計算機,IBM,Nvidia和美國能源部組成一個超級計算機超級團隊

CNET技術信息網7月15日國際報道: IBM將與Nvidia和美國能源部合作建立兩個新的杰出超級計算機中心. 這項合作的工作主要集中在兩個方面&#xff0c;一個是確保應用程序可以充分利用超級計算機的強大性能&#xff0c;另一個是收集開發人員&#xff0c;工程師和科學家的反饋.這兩個…

C#Convert.ToInt32(char)方法-將char值轉換為int

C&#xff03;Convert.ToInt32(char)方法 (C# Convert.ToInt32(char) Method) Convert.ToInt32(char) Method is used to convert a specific char value to its equivalent integer (int 32 signed number) (It can also be known as ASCII value). Convert.ToInt32(char)方法…

華為p40論壇_華為高端旗艦繼續發力!麒麟990 5G+超感知三攝,256GB降價799元

小米10、一加8&#xff0c;vivo NEX3S等高性能旗艦產品現已在市場上發售。其中&#xff0c;5G旗艦華為P40也在銷售團隊中&#xff0c;并且最近成為最受歡迎的旗艦產品。由于華為P40高端版從799元跌至4189元&#xff0c;消費者可以以不到800元的價格購買低價高性能旗艦產品&…

計算機基礎.doc,大學生計算機基礎.doc

WORD格式 整理分享范文范例 參考指導電子計算機的誕生1計算機的發展經歷了4個時代&#xff0c;各個時代劃分的原則是根據( )。A、計算機所采用的電子器件B、計算機的運算速度C、程序設計語言D、計算機的存儲量正確答案&#xff1a;A?2世界上第一臺電子計算機誕生于( )年。A、1…

移動端類似IOS的滾動年月控件(需要jQuery和iScroll)

http://www.cnblogs.com/ccblogs/p/5260949.html 一. 效果圖 二. 功能介紹 支持滾動和點擊選擇年月。&#xff08;目前只支持設置年月的最大最小值&#xff0c;不支持整體的最大最小值&#xff09; 三. 代碼 1. 在你的html中添加如下代碼&#xff1a; 直接加載<body>里面…

css 橫向滾動隱藏滾動條_使用CSS滾動時如何隱藏滾動條?

css 橫向滾動隱藏滾動條Introduction: 介紹&#xff1a; It is always nice to have a responsive website or web page, to create such websites or web pages we have to make use of our developing skills to a great extent to bring about the functionality as well a…

DrawerLayout側滑詳解

前面我們說了自定義側滑菜單&#xff0c;也說了SlidingMenu的使用&#xff0c;這一節我們再來說下DrawerLayout。DrawerLayout是Support Library包中實現了側滑菜單效果的控件&#xff0c;可以說DrawerLayout是因為第三方控件如SlidingMenu等出現之后&#xff0c;google借鑒而出…

華為筆記本計算機在哪,新一代華為MateBook 的機會在哪里?

2017年5月23日 在德國柏林&#xff0c;華為正式面向全球消費者發布了MateBook系列新品——13英寸靈動商務筆記本MateBook X、12英寸時尚二合一筆記本MateBook E及15.6英寸商務影音筆記本MateBook D。今天筆記本市場似乎是一個比較穩定的市場&#xff0c;筆記本的銷量增長不快&a…

python 字符串 變量_檢查變量是否為字符串的Python程序

python 字符串 變量Python | 檢查變量是否為字符串 (Python | Check if a variable is a string) To check whether a defined variable is a string type or not, we can use two functions which are Python library functions, 要檢查定義的變量是否為字符串類型&#xff0c…

mysql shell

mysql 查詢10分鐘以內的數據:select *from t_agent where int_last_login>CURRENT_TIMESTAMP - INTERVAL 10 MINUTE; mysql關聯多表進行update更新操作UPDATE TrackINNER JOIN MVON Track.trkidMV.mvidSET Track.is_showMV.is_showWHERE trkid<6等同于UPDATE Track,MVSET…

kaggle計算機視覺比賽技巧,9. 計算機視覺 - 9.12. 實戰Kaggle比賽:圖像分類(CIFAR-10) - 《動手學深度學習》 - 書棧網 · BookStack...

9.12. 實戰Kaggle比賽&#xff1a;圖像分類(CIFAR-10)到目前為止&#xff0c;我們一直在用Gluon的data包直接獲取NDArray格式的圖像數據集。然而&#xff0c;實際中的圖像數據集往往是以圖像文件的形式存在的。在本節中&#xff0c;我們將從原始的圖像文件開始&#xff0c;一步…