国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

實(shí)驗(yàn)中心網(wǎng)站建設(shè)媒體軟文發(fā)稿

實(shí)驗(yàn)中心網(wǎng)站建設(shè),媒體軟文發(fā)稿,公司企業(yè)官網(wǎng),wordpress外貿(mào)服裝營(yíng)銷(xiāo)型主題一、TCP 狀態(tài)轉(zhuǎn)換 瀏覽器訪(fǎng)問(wèn)網(wǎng)址,TCP傳輸全過(guò)程 二、TCP協(xié)議的通信過(guò)程 三、TCP 通信流程 // TCP 通信的流程 // 服務(wù)器端 (被動(dòng)接受連接的角色) 1. 創(chuàng)建一個(gè)用于監(jiān)聽(tīng)的套接字- 監(jiān)聽(tīng):監(jiān)聽(tīng)有客戶(hù)端的連接- 套接字:這…

一、TCP 狀態(tài)轉(zhuǎn)換

瀏覽器訪(fǎng)問(wèn)網(wǎng)址,TCP傳輸全過(guò)程

二、TCP協(xié)議的通信過(guò)程?

三、TCP 通信流程?

// TCP 通信的流程
// 服務(wù)器端 (被動(dòng)接受連接的角色)
1. 創(chuàng)建一個(gè)用于監(jiān)聽(tīng)的套接字- 監(jiān)聽(tīng):監(jiān)聽(tīng)有客戶(hù)端的連接- 套接字:這個(gè)套接字其實(shí)就是一個(gè)文件描述符
2. 將這個(gè)監(jiān)聽(tīng)文件描述符和本地的IP和端口綁定(IP和端口就是服務(wù)器的地址信息)- 客戶(hù)端連接服務(wù)器的時(shí)候使用的就是這個(gè)IP和端口
3. 設(shè)置監(jiān)聽(tīng),監(jiān)聽(tīng)的fd開(kāi)始工作
4. 阻塞等待,當(dāng)有客戶(hù)端發(fā)起連接,解除阻塞,接受客戶(hù)端的連接,會(huì)得到一個(gè)和客戶(hù)端通信的套接字
(fd)
5. 通信- 接收數(shù)據(jù)- 發(fā)送數(shù)據(jù)
6. 通信結(jié)束,斷開(kāi)連接
// 客戶(hù)端
1. 創(chuàng)建一個(gè)用于通信的套接字(fd)
2. 連接服務(wù)器,需要指定連接的服務(wù)器的 IP 和 端口
3. 連接成功了,客戶(hù)端可以直接和服務(wù)器通信- 接收數(shù)據(jù)- 發(fā)送數(shù)據(jù)
4. 通信結(jié)束,斷開(kāi)連接


套接字通信的客戶(hù)端和服務(wù)端的實(shí)現(xiàn)_呵呵噠( ̄▽ ̄)"的博客-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/132046488?spm=1001.2014.3001.5501

四 、解析HTTP請(qǐng)求報(bào)文

4.1 讀取數(shù)據(jù)到緩沖區(qū) bool http_conn::read()

// 循環(huán)讀取客戶(hù)數(shù)據(jù),直到無(wú)數(shù)據(jù)可讀或者對(duì)方關(guān)閉連接
bool http_conn::read() {// printf("一次性讀完數(shù)據(jù)\n");if( m_read_idx >= READ_BUFFER_SIZE ) {return false;}int bytes_read = 0;//讀取到的字節(jié)while(true) {//開(kāi)始保存數(shù)據(jù)// 數(shù)組起始位置(0) + 已經(jīng)讀的數(shù)據(jù)位置(100) = 下次開(kāi)始寫(xiě)的位置(101)// 從m_read_buf + m_read_idx索引出開(kāi)始保存數(shù)據(jù),大小是READ_BUFFER_SIZE - m_read_idxbytes_read = recv(m_sockfd, m_read_buf + m_read_idx, READ_BUFFER_SIZE - m_read_idx, 0 );if (bytes_read == -1) {if( errno == EAGAIN || errno == EWOULDBLOCK ) {// 沒(méi)有數(shù)據(jù)break;}return false;   } else if (bytes_read == 0) {   // 對(duì)方關(guān)閉連接return false;}m_read_idx += bytes_read;//讀到數(shù)據(jù),更新索引}// printf("讀到了數(shù)據(jù): %s\n",m_read_buf);return true;
}

4.2?有限狀態(tài)機(jī)

邏輯單元內(nèi)部的一種高效編程方法:有限狀態(tài)機(jī)(finite state machine)。有的應(yīng)用層協(xié)議頭部包含數(shù)據(jù)包類(lèi)型字段,每種類(lèi)型可以映射為邏輯單元的一種執(zhí)行狀態(tài),服務(wù)器可以根據(jù)它來(lái)編寫(xiě)相應(yīng)的處理邏輯。如下是一種狀態(tài)獨(dú)立的有限狀態(tài)機(jī):

STATE_MACHINE( Package _pack )
{PackageType _type = _pack.GetType();switch( _type ){case type_A:process_package_A( _pack );break;case type_B:process_package_B( _pack );break;}
}

這是一個(gè)簡(jiǎn)單的有限狀態(tài)機(jī),只不過(guò)該狀態(tài)機(jī)的每個(gè)狀態(tài)都是相互獨(dú)立的,即狀態(tài)之間沒(méi)有相互轉(zhuǎn)移。狀態(tài)之間的轉(zhuǎn)移是需要狀態(tài)機(jī)內(nèi)部驅(qū)動(dòng),如下代碼:

STATE_MACHINE()
{State cur_State = type_A;while( cur_State != type_C ){Package _pack = getNewPackage();switch( cur_State ){case type_A:process_package_state_A( _pack );cur_State = type_B;break;case type_B:process_package_state_B( _pack );cur_State = type_C;break;}}
}

該狀態(tài)機(jī)包含三種狀態(tài):type_A、type_B 和 type_C,其中 type_A 是狀態(tài)機(jī)的開(kāi)始狀態(tài),type_C 是狀態(tài)機(jī)的結(jié)束狀態(tài)。狀態(tài)機(jī)的當(dāng)前狀態(tài)記錄在 cur_State 變量中。在一趟循環(huán)過(guò)程中,狀態(tài)機(jī)先通過(guò) getNewPackage 方法獲得一個(gè)新的數(shù)據(jù)包,然后根據(jù) cur_State 變量的值判斷如何處理該數(shù)據(jù)包。數(shù)據(jù)包處理完之后,狀態(tài)機(jī)通過(guò)給 cur_State 變量傳遞目標(biāo)狀態(tài)值來(lái)實(shí)現(xiàn)狀態(tài)轉(zhuǎn)移。那么當(dāng)狀態(tài)機(jī)進(jìn)入下一趟循環(huán)時(shí),它將執(zhí)行新的狀態(tài)對(duì)應(yīng)的邏輯。

4.3 HTTP 請(qǐng)求格式

>>http get請(qǐng)求報(bào)文的格式
請(qǐng)求行\(zhòng)r\n
請(qǐng)求頭\r\n
空行(\r\n)提示: 每項(xiàng)信息之間都需要一個(gè)\r\n,是由http協(xié)議規(guī)定************************************************
************************************************
>>http post請(qǐng)求報(bào)文的格式
請(qǐng)求行\(zhòng)r\n
請(qǐng)求頭\r\n
空行(\r\n)
請(qǐng)求體提示: 請(qǐng)求體就是瀏覽器發(fā)送給服務(wù)器的數(shù)據(jù)

在HTTP報(bào)文中,每一行的數(shù)據(jù)有\r\n作為結(jié)束字符,空行則是僅僅是字符\r\n。因此,可以通過(guò)查找\r\n將報(bào)文拆解成單獨(dú)的行進(jìn)行解析,項(xiàng)目中便是利用了這一點(diǎn)。?

推薦文章:?

http請(qǐng)求報(bào)文與響應(yīng)報(bào)文_構(gòu)造http請(qǐng)求報(bào)文,發(fā)送到天氣預(yù)報(bào)的服務(wù)器,并獲取http響應(yīng)報(bào)文,將報(bào)文進(jìn)行解析獲_JSon liu的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_45912307/article/details/109454522

Http請(qǐng)求報(bào)文格式和響應(yīng)報(bào)文格式-騰訊云開(kāi)發(fā)者社區(qū)-騰訊云 (tencent.com)icon-default.png?t=N7T8https://cloud.tencent.com/developer/article/1953222我的往期文章:Web服務(wù)器簡(jiǎn)介及HTTP協(xié)議_呵呵噠( ̄▽ ̄)"的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_41987016/article/details/132610837?spm=1001.2014.3001.5501

4.4?狀態(tài)轉(zhuǎn)換圖

狀態(tài)轉(zhuǎn)換圖
狀態(tài)轉(zhuǎn)換圖

4.5 主狀態(tài)機(jī)狀態(tài)和從狀態(tài)機(jī)狀態(tài)

(1)?從狀態(tài)機(jī)狀態(tài)

>>從狀態(tài)機(jī)邏輯

負(fù)責(zé)讀取buffer中的數(shù)據(jù),將每行數(shù)據(jù)末尾的\r\n置為\0\0,并更新從狀態(tài)機(jī)在buffer中讀取的位置m_checked_idx,從此來(lái)驅(qū)動(dòng)主狀態(tài)機(jī)解析

從狀態(tài)機(jī)從m_read_buf中逐字節(jié)讀取,判斷當(dāng)前字節(jié)是否為\r

  • 接下來(lái)的字符是\n,將\r\n修改成\0\0,將m_checked_idx指向下一行的開(kāi)頭,則返回LINE_OK
  • 然后達(dá)到了buffer末尾,表示buffer還需要繼續(xù)接收,返回LINE_OPEN
  • 否則,表示語(yǔ)法錯(cuò)誤,返回LINE_BAD

當(dāng)前字節(jié)不是\r,判斷是否是\n

  • 【注意】什么時(shí)候會(huì)是②這種情況?
一般是上次讀取到\r就到了buffer末尾,沒(méi)有接收完整,再次接收時(shí)會(huì)出現(xiàn)這種情況。
  • 【判斷】如果前一個(gè)字符是\r,則將\r\n修改成\0\0,將m_checked_idx指向下一行的開(kāi)頭,則返回LINE_OK

當(dāng)前字節(jié)既不是\r,也不是\n

  • 表示接受不完整,需要繼續(xù)接收,返回LINE_OPEN
/*從狀態(tài)機(jī),用于分析出一行內(nèi)容返回值為行的讀取狀態(tài),由LINE_OK,LINE_BAD,LINE_OPENm_read_idx:指向緩沖區(qū)m_read_buf的數(shù)據(jù)末尾的下一個(gè)字節(jié)m_checked_idx:指向從狀態(tài)機(jī)當(dāng)前正在分析的字節(jié)
*/
// 解析一行,判斷依據(jù)\r\n
http_conn::LINE_STATUS http_conn::parse_line() {char temp;for ( ; m_checked_idx < m_read_idx; ++m_checked_idx ) {// temp 為將要分析的字節(jié)temp = m_read_buf[ m_checked_idx ];// 如果當(dāng)前是\r字符,則有可能會(huì)讀取到完整行if ( temp == '\r' ) {// 下一個(gè)字符達(dá)到了buffer結(jié)尾,則接收不完整,需要繼續(xù)接收if ( ( m_checked_idx + 1 ) == m_read_idx ) {return LINE_OPEN;} // 下一個(gè)字符是\n,將\r\n改為\0\0else if ( m_read_buf[ m_checked_idx + 1 ] == '\n' ) {m_read_buf[ m_checked_idx++ ] = '\0';m_read_buf[ m_checked_idx++ ] = '\0';return LINE_OK;}// 如果都不符合,則返回語(yǔ)法錯(cuò)誤return LINE_BAD;} // 如果當(dāng)前字符是\n,也有可能讀取到完整行// 一般是上次讀取到\r就到 buffer 末尾了,沒(méi)有接收完整,再次接收時(shí)會(huì)出現(xiàn)這種情況else if( temp == '\n' )  {// 前一個(gè)字符是\r,則接收完整if( ( m_checked_idx > 1) && ( m_read_buf[ m_checked_idx - 1 ] == '\r' ) ) {m_read_buf[ m_checked_idx-1 ] = '\0';m_read_buf[ m_checked_idx++ ] = '\0';return LINE_OK;}return LINE_BAD;}}// 并沒(méi)有找到\r\n,需要繼續(xù)接收return LINE_OPEN;
}
例如:
>>http get請(qǐng)求報(bào)文的格式
請(qǐng)求行\(zhòng)r\n
請(qǐng)求頭\r\n
空行(\r\n)提示: 每項(xiàng)信息之間都需要一個(gè)\r\n,是由http協(xié)議規(guī)定>>http get請(qǐng)求報(bào)文的格式
請(qǐng)求行\(zhòng)0\0
請(qǐng)求頭\0\0
空行(\0\0)

(2)主從狀態(tài)機(jī),http_conn::process_read()

>>解析報(bào)文整體流程

process_read 通過(guò) while 循環(huán),將主狀態(tài)機(jī)進(jìn)行封裝,對(duì)報(bào)文的每一行進(jìn)行循環(huán)處理

http_conn::process_read() 是一個(gè)HTTP請(qǐng)求處理函數(shù),用于解析HTTP請(qǐng)求報(bào)文

① 解析一行數(shù)據(jù),得到不同狀態(tài)(包括請(qǐng)求行、請(qǐng)求頭、請(qǐng)求體

  • LINE_OK
  • LINE_BAD
  • LINE_OPEN

根據(jù)不同的狀態(tài),解析請(qǐng)求行、請(qǐng)求頭或請(qǐng)求體,并進(jìn)行相應(yīng)的處理

  • CHECK_STATE_REQUESTLINE ---- parse_request_line()
  • CHECK_STATE_HEADER ---- parse_headers()
  • CHECK_STATE_CONTENT ---- parse_content()

?③ 對(duì)于GET請(qǐng)求,根據(jù)具體的請(qǐng)求信息進(jìn)行預(yù)處理,分析目標(biāo)文件屬性,并將其映射到內(nèi)存地址m_file_address

  • do_request()

返回處理結(jié)果,包括成功、失敗或請(qǐng)求不完整等狀態(tài)碼???????

>>主從狀態(tài)機(jī)模式

主從狀態(tài)機(jī)模式:http_conn::process_read()用以應(yīng)對(duì)不同的狀態(tài)處理。

  • 一個(gè)狀態(tài)機(jī)作為主要的控制器,而其他狀態(tài)機(jī)則被設(shè)計(jì)為從狀態(tài)機(jī)
  • 主狀態(tài)機(jī)將它們之間的通信和事件處理進(jìn)行協(xié)調(diào)
  • 主狀態(tài)機(jī)是在系統(tǒng)啟動(dòng)時(shí)創(chuàng)建的
  • 從狀態(tài)機(jī)可以在系統(tǒng)運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建、注冊(cè)或注銷(xiāo)

主狀態(tài)機(jī) process_read() 中進(jìn)行循環(huán),直到解析完整個(gè) HTTP 請(qǐng)求數(shù)據(jù)

當(dāng)且僅當(dāng)解析到請(qǐng)求體時(shí),才需要進(jìn)一步判斷是否已經(jīng)解析完整個(gè) HTTP 請(qǐng)求數(shù)據(jù)

表示若當(dāng)前正在解析請(qǐng)求體,并且從狀態(tài)機(jī)已經(jīng)成功解析了一行請(qǐng)求數(shù)據(jù),則需要繼續(xù)解析下一行請(qǐng)求數(shù)據(jù)?

(m_check_state == CHECK_STATE_CONTENT) && (line_status == LINE_OK)

或者從狀態(tài)機(jī)還未成功解析出一行完整的請(qǐng)求數(shù)據(jù),就需要不斷循環(huán)調(diào)用從狀態(tài)機(jī)、解析請(qǐng)求數(shù)據(jù)

 ((line_status = parse_line()) == LINE_OK))

?(line_status = parse_line()) 表示調(diào)用從狀態(tài)機(jī) parse_line() ,并將返回值賦給變量 line_status

  • 解析成功,line_status = LINE_OK
  • 否則,line_statusLINE_OPEN、LINE_BAD

直到解析完成整個(gè) HTTP 請(qǐng)求數(shù)據(jù)

// 主狀態(tài)機(jī),解析請(qǐng)求
http_conn::HTTP_CODE http_conn::process_read() {// 定義初始狀態(tài)LINE_STATUS line_status = LINE_OK;HTTP_CODE ret = NO_REQUEST;char* text = 0;// 解析一行數(shù)據(jù),得到不同狀態(tài)// OK表示正常// 主狀態(tài)機(jī) && 從狀態(tài)機(jī) || 解析到一行完整數(shù)據(jù)(或者請(qǐng)求體)// 這里主狀態(tài)機(jī)指的是process_read()函數(shù),從狀態(tài)機(jī)指的是parse_line()while (((m_check_state == CHECK_STATE_CONTENT) && (line_status == LINE_OK))|| ((line_status = parse_line()) == LINE_OK)) {// 獲取一行數(shù)據(jù)text = get_line();m_start_line = m_checked_idx;printf( "got 1 http line: %s\n", text );switch ( m_check_state ) {case CHECK_STATE_REQUESTLINE: {// 解析請(qǐng)求行,也就是 GET 中的 GET/*通過(guò)請(qǐng)求行的解析我們可以判斷該HTTP請(qǐng)求的類(lèi)型(GET/POST),而請(qǐng)求行中最重要的部分就是URL部分將這部分保存下來(lái)用于后面的生成HTTP響應(yīng)*/ret = parse_request_line( text );if ( ret == BAD_REQUEST ) {return BAD_REQUEST;}break;// 正常解析就break}case CHECK_STATE_HEADER: {ret = parse_headers( text );//解析請(qǐng)求頭,GET 和 POST 中空行以上,請(qǐng)求行以下的部分if ( ret == BAD_REQUEST ) {return BAD_REQUEST;} else if ( ret == GET_REQUEST ) {//遇到換行符就默認(rèn)你解析完請(qǐng)求頭,不管后面還有沒(méi)有內(nèi)容return do_request();//解析具體的請(qǐng)求信息}break;}case CHECK_STATE_CONTENT: {/*解析請(qǐng)求數(shù)據(jù),對(duì)于GET來(lái)說(shuō)這部分是空的,因?yàn)檫@部分內(nèi)容已經(jīng)以明文的方式包含在了請(qǐng)求行中的URL部分了;只有POST的這部分是有數(shù)據(jù)的*/ret = parse_content( text );if ( ret == GET_REQUEST ) {/*do_request() 需要做:需要首先對(duì) GET請(qǐng)求 和不同的 POST請(qǐng)求(登錄、注冊(cè)、請(qǐng)求圖片、視頻等等)做不同的預(yù)處理,然后分析目標(biāo)文件的屬性,若目標(biāo)文件存在、對(duì)所有用戶(hù)可讀且不是目錄時(shí),則使用mmap將其映射到內(nèi)存地址m_file_address處,并告訴調(diào)用者獲取文件成功*/return do_request();}line_status = LINE_OPEN;break;}default: {return INTERNAL_ERROR;}}}return NO_REQUEST;//主狀態(tài)機(jī)請(qǐng)求不完整
}

注意在http_conn.h 編寫(xiě) get_line()函數(shù)

// m_start_line是已經(jīng)解析的字符
// get_line用于將指針向后偏移,指向未處理的字符
/*m_start_line是行在bufffer中的起始位置,將該位置后面的數(shù)據(jù)賦給text此時(shí)從狀態(tài)機(jī)已提前將一行的末尾字符\r\n變?yōu)閈0\0,所以text可以直接取出完整的行進(jìn)行解析
*/
char* get_line() { return m_read_buf + m_start_line;
}

??(3)主狀態(tài)機(jī)狀態(tài)?

>>主狀態(tài)機(jī)邏輯?

主狀態(tài)機(jī)初始狀態(tài)是CHECK_STATE_REQUESTLINE,通過(guò)調(diào)用從狀態(tài)機(jī)來(lái)驅(qū)動(dòng)主狀態(tài)機(jī),在主狀態(tài)機(jī)進(jìn)行解析前,從狀態(tài)機(jī)已經(jīng)將每一行的末尾\r\n符號(hào)改為\0\0,以便于主狀態(tài)機(jī)直接取出對(duì)應(yīng)字符串進(jìn)行處理。

CHECK_STATE_REQUESTLINE

  1. 主狀態(tài)機(jī)的初始狀態(tài),調(diào)用parse_request_line函數(shù)解析請(qǐng)求行
  2. 解析函數(shù)從m_read_buf中解析HTTP請(qǐng)求行,獲得請(qǐng)求方法,目標(biāo)URLHTTP版本號(hào)
  3. 解析完成后主狀態(tài)機(jī)的狀態(tài)變?yōu)?strong>CHECK_STATE_HEADER
// 解析HTTP請(qǐng)求行,獲得請(qǐng)求方法,目標(biāo)URL,以及HTTP版本號(hào)
http_conn::HTTP_CODE http_conn::parse_request_line(char* text) {// 在HTTP報(bào)文中,請(qǐng)求行用來(lái)說(shuō)明請(qǐng)求類(lèi)型,要訪(fǎng)問(wèn)的資源以及所使用的HTTP版本,// 其中各個(gè)部分之間通過(guò)\t或空格分隔// 請(qǐng)求行中最先含有空格和\t任一字符的位置并返回// GET /index.html HTTP/1.1m_url = strpbrk(text, " \t"); // 判斷第二個(gè)參數(shù)中的字符哪個(gè)在text中最先出現(xiàn)// 如果沒(méi)有空格或\t,則報(bào)文格式有誤if (! m_url) { return BAD_REQUEST;}// 將該位置改為\0,用于將前面數(shù)據(jù)取出// GET\0/index.html HTTP/1.1*m_url++ = '\0';    // 置位空字符,字符串結(jié)束符// 取出數(shù)據(jù),并通過(guò)與GET和POST比較,以確定請(qǐng)求方式char* method = text;if ( strcasecmp(method, "GET") == 0 ) { // 忽略大小寫(xiě)比較m_method = GET;} else {return BAD_REQUEST;}// /index.html HTTP/1.1// 檢索字符串 str1 中第一個(gè)不在字符串 str2 中出現(xiàn)的字符下標(biāo)。m_version = strpbrk( m_url, " \t" );if (!m_version) {return BAD_REQUEST;}*m_version++ = '\0';// 僅支持HTTP/1.1if (strcasecmp( m_version, "HTTP/1.1") != 0 ) {return BAD_REQUEST;}/*** http://192.168.110.129:10000/index.html* 對(duì)請(qǐng)求資源前7個(gè)字符進(jìn)行判斷* 這里主要是有些報(bào)文的請(qǐng)求資源中會(huì)帶有http://,這里需要對(duì)這種情況進(jìn)行單獨(dú)處理*/if (strncasecmp(m_url, "http://", 7) == 0 ) {   m_url += 7;// 在參數(shù) str 所指向的字符串中搜索第一次出現(xiàn)字符 c(一個(gè)無(wú)符號(hào)字符)的位置。m_url = strchr( m_url, '/' );}// 同樣增加https情況if (strncasecmp(m_url, "https://", 8) == 0 ) {   m_url += 8;m_url = strchr( m_url, '/' );}// 一般的不會(huì)帶有上述兩種符號(hào),直接是單獨(dú)的/或/后面帶訪(fǎng)問(wèn)資源if ( !m_url || m_url[0] != '/' ) {return BAD_REQUEST;}// 請(qǐng)求行處理完畢,將主狀態(tài)機(jī)轉(zhuǎn)移處理請(qǐng)求頭m_check_state = CHECK_STATE_HEADER; // 檢查狀態(tài)變成檢查頭return NO_REQUEST;
}

解析完請(qǐng)求行后,主狀態(tài)機(jī)繼續(xù)分析請(qǐng)求頭。在報(bào)文中,請(qǐng)求頭和空行的處理使用的同一個(gè)函數(shù),這里通過(guò)判斷當(dāng)前的text首位是不是\0字符。

  • 若是,則表示當(dāng)前處理的是空行
  • 若不是,則表示當(dāng)前處理的是請(qǐng)求頭?

CHECK_STATE_HEADER

  1. 調(diào)用parse_headers函數(shù)解析請(qǐng)求頭部信息
  2. 判斷是空行還是請(qǐng)求頭。若是空行,進(jìn)而判斷Content-length是否為0,如果不是0,表明是POST請(qǐng)求,則狀態(tài)轉(zhuǎn)移到CHECK_STATE_CONTENT;否則說(shuō)明是GET,則報(bào)文解析結(jié)束
  3. 若解析的是請(qǐng)求頭部字段,則主要分析Connection字段,Content-length字段等
  4. Connection字段判斷是keep-alive 還是 close,決定是長(zhǎng)連接還是短連接;如果是長(zhǎng)連接,則將linger標(biāo)志設(shè)置為true
  5. Content-length字段,這里用于讀取post請(qǐng)求的消息體長(zhǎng)度
// 解析HTTP請(qǐng)求的一個(gè)頭部信息
http_conn::HTTP_CODE http_conn::parse_headers(char* text) {   // 遇到空行,表示頭部字段解析完畢if( text[0] == '\0' ) {// 判斷是GET 還是 POST 請(qǐng)求/*如果HTTP請(qǐng)求有消息體,則還需要讀取m_content_length字節(jié)的消息體,狀態(tài)機(jī)轉(zhuǎn)移到CHECK_STATE_CONTENT狀態(tài)*/if ( m_content_length != 0 ) {// POST需要跳轉(zhuǎn)到消息體處理狀態(tài)m_check_state = CHECK_STATE_CONTENT;return NO_REQUEST;}// 否則說(shuō)明我們已經(jīng)得到了一個(gè)完整的HTTP請(qǐng)求return GET_REQUEST;} // 解析請(qǐng)求頭部連接字段else if ( strncasecmp( text, "Connection:", 11 ) == 0 ) {// 處理Connection 頭部字段  Connection: keep-alivetext += 11;// 跳過(guò)空格和\t字符text += strspn( text, " \t" );if ( strcasecmp( text, "keep-alive" ) == 0 ) {// 如果是長(zhǎng)連接,則將linger標(biāo)志設(shè)置為truem_linger = true;}} // 解析請(qǐng)求頭部?jī)?nèi)容長(zhǎng)度字段else if ( strncasecmp( text, "Content-Length:", 15 ) == 0 ) {// 處理Content-Length頭部字段text += 15;text += strspn( text, " \t" );m_content_length = atol(text);} // 解析請(qǐng)求頭部HOST字段else if ( strncasecmp( text, "Host:", 5 ) == 0 ) {// 處理Host頭部字段text += 5;text += strspn( text, " \t" );m_host = text;} else {printf( "oop! unknow header %s\n", text );}return NO_REQUEST;
}

GETPOST請(qǐng)求報(bào)文的區(qū)別之一是有無(wú)消息體部分。GET請(qǐng)求沒(méi)有消息體,當(dāng)解析完空行之后,便完成了報(bào)文的解析。僅用從狀態(tài)機(jī)的狀態(tài)(line_status = parse_line()) == LINE_OK語(yǔ)句即可。

POST請(qǐng)求報(bào)文中,消息體的末尾沒(méi)有任何字符

>>http post請(qǐng)求報(bào)文的格式
請(qǐng)求行\(zhòng)r\n
請(qǐng)求頭\r\n
空行(\r\n)
請(qǐng)求體

所以無(wú)法使用從狀態(tài)機(jī)的狀態(tài),轉(zhuǎn)而使用主狀態(tài)機(jī)的狀態(tài)作為循環(huán)入口條件

((m_check_state == CHECK_STATE_CONTENT) && (line_status == LINE_OK))

解析完消息體之后,報(bào)文的完整解析也就完成了,此時(shí)主狀態(tài)機(jī)的狀態(tài)還是CHECK_STATE_CONTENT。意味著符合循環(huán)入口條件,還會(huì)再次進(jìn)入循環(huán)。為此,需要在完成請(qǐng)求體解析后,將line_status變量更改為LINE_OPEN,便可跳出循環(huán),完成報(bào)文解析任務(wù)

while (((m_check_state == CHECK_STATE_CONTENT) && (line_status == LINE_OK))|| ((line_status = parse_line()) == LINE_OK)) {// 獲取一行數(shù)據(jù)text = get_line();m_start_line = m_checked_idx;printf( "got 1 http line: %s\n", text );switch ( m_check_state ) {......case CHECK_STATE_CONTENT: {ret = parse_content( text );if ( ret == GET_REQUEST ) {return do_request();}// 在完成請(qǐng)求體解析后,將line_status變量更改為L(zhǎng)INE_OPEN,跳出循環(huán),完成報(bào)文解析任務(wù)line_status = LINE_OPEN;break;}......}
}

CHECK_STATE_HEADER

  • 僅用于解析POST請(qǐng)求,調(diào)用parse_content函數(shù)解析請(qǐng)求體
  • 用于保存post請(qǐng)求消息體,為后面的登錄和注冊(cè)做準(zhǔn)備
// 我們沒(méi)有真正解析HTTP請(qǐng)求的消息體,只是判斷它是否被完整的讀入了
http_conn::HTTP_CODE http_conn::parse_content( char* text ) {// 判斷buffer中是否讀取了消息體if ( m_read_idx >= ( m_content_length + m_checked_idx ) ){text[ m_content_length ] = '\0';return GET_REQUEST;}return NO_REQUEST;
}

參考和推薦文章:

最新版Web服務(wù)器項(xiàng)目詳解 - 05 http連接處理(中) (qq.com)icon-default.png?t=N7T8https://mp.weixin.qq.com/s?__biz=MzAxNzU2MzcwMw==&mid=2649274278&idx=7&sn=d1ab62872c3ddac765d2d80bbebfb0dd&chksm=83ffbefeb48837e808caad089f23c340e1348efb94bef88be355f4d9aedb0f9784e1f9e072b1&scene=178&cur_album_id=1339230165934882817#rd【從0開(kāi)始編寫(xiě)webserver·基礎(chǔ)篇#02】服務(wù)器的核心---I/O處理單元和任務(wù)類(lèi) - dayceng - 博客園 (cnblogs.com)icon-default.png?t=N7T8https://www.cnblogs.com/DAYceng/p/17418584.html#%E5%A4%84%E7%90%86%E6%96%B0%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E8%BF%9E%E6%8E%A5%E8%AF%B7%E6%B1%82

http://aloenet.com.cn/news/42146.html

相關(guān)文章:

  • 電子書(shū)城網(wǎng)站開(kāi)發(fā)項(xiàng)目概況網(wǎng)絡(luò)推廣引流方式
  • wordpress用哪種緩存器seo排名軟件哪個(gè)好用
  • 做淘寶必備網(wǎng)站手機(jī)seo關(guān)鍵詞優(yōu)化
  • 做網(wǎng)站是干什么用的百度營(yíng)銷(xiāo)推廣登錄平臺(tái)
  • 網(wǎng)站建設(shè) 軟件有哪些內(nèi)容最近剛發(fā)生的新聞
  • 大連做網(wǎng)站首選領(lǐng)超科技域名注冊(cè)服務(wù)網(wǎng)站哪個(gè)好
  • 網(wǎng)站建站所用的技術(shù)自動(dòng)優(yōu)化句子的軟件
  • 長(zhǎng)春火車(chē)站24小時(shí)人工客服電話(huà)香飄飄奶茶
  • 介紹做網(wǎng)站的標(biāo)題廈門(mén)人才網(wǎng)個(gè)人登錄
  • 韶關(guān)城鄉(xiāng)建設(shè)部網(wǎng)站首頁(yè)螺螄粉營(yíng)銷(xiāo)策劃方案
  • 網(wǎng)站群的建設(shè)目標(biāo)濟(jì)南seo怎么優(yōu)化
  • 寧德網(wǎng)站建設(shè)維護(hù)如何優(yōu)化網(wǎng)站排名
  • wordpress主題后空白seo知識(shí)分享
  • 做網(wǎng)站底色怎么選網(wǎng)站seo排名公司
  • 蘭州互聯(lián)網(wǎng)公司seo深度解析
  • 怎樣建設(shè)網(wǎng)站公司百度app關(guān)鍵詞優(yōu)化
  • 質(zhì)感企業(yè)網(wǎng)站導(dǎo)航用ps怎么做百度圖片搜索網(wǎng)頁(yè)版
  • 關(guān)于網(wǎng)站開(kāi)發(fā)專(zhuān)業(yè)的pptseo診斷專(zhuān)家
  • 網(wǎng)站建設(shè)詳細(xì)教程寧波seo推廣優(yōu)化公司
  • 河北網(wǎng)站建設(shè)排名站長(zhǎng)seo查詢(xún)工具
  • 便宜的做網(wǎng)站公司關(guān)鍵詞seo公司推薦
  • 深圳專(zhuān)門(mén)做網(wǎng)站阿里云域名查詢(xún)和注冊(cè)
  • 簡(jiǎn)易網(wǎng)站開(kāi)發(fā)巨量引擎
  • 電子商務(wù)網(wǎng)站服務(wù)器上海網(wǎng)絡(luò)營(yíng)銷(xiāo)公司
  • dw手機(jī)網(wǎng)站建設(shè)500個(gè)游戲推廣群
  • 班級(jí)網(wǎng)站素材下載百度推廣有哪些推廣方式
  • 大型網(wǎng)站制作梅州網(wǎng)絡(luò)推廣
  • 百度網(wǎng)站錄入網(wǎng)站整站優(yōu)化
  • 建行app官方下載搜索引擎優(yōu)化中的步驟包括
  • 淘寶優(yōu)惠券微網(wǎng)站開(kāi)發(fā)手機(jī)版怎么用百度快照