tomcat Http11NioProtocol如何解析http請求及如何解決TCP拆包粘包


前言

tomcat是常用的Web 應用服務器,目前國內有很多文章講解了tomcat架構,請求流程等,但是沒有如何解析http請求及如何解決TCP粘包拆包,所以這篇文章的目的就是介紹這塊內容,一下內容完全是個人查看tomcat nio 相關源碼來總結的,源碼版本9.0.30,歡迎提問,歡迎指出錯誤。

請求解析

參數在請求行時的請求形式

GET /myServlet?name=zhangsan HTTP/1.1
Connection: keep-alive

參數在請求體時的請求形式

POST /myServlet HTTP/1.1

Connection: keep-alive

 

name=zhangsan

中間有一個空行表示請求頭和請求體的分界。

解析請求行

以 GET /myServlet?name=zhangsan HTTP/1.1為例

將請求行按空格進行分割,將method(POST),requestURI(/myServlet ),protocol(HTTP/1.1 )存起來

將?之后的數據存入queryString(name=zhangsan)存起來。

一直遇見換行符解析結束。

解析請求頭

以這個為例

Content-Length: 13

Connection: keep-alive

 

name=zhangsan

解析過程很簡單,以":"進行分割,一直到讀取到一個只有換行符的空行,請求頭解析結束。

解析請求體

請求體解析是通過請求頭中的Content-Length來進行解析的,讀取Content-Length值中對應的字節數。

如何解決拆包粘包

知道了請求結果和解析流程,下面就介紹一下怎樣處理拆包粘包。

粘包

粘包的解決是非常簡單的,比如粘包后是這樣的數據。

POST /myServlet?name=liuhao HTTP/1.1

Content-Length: 13

 

name=zhangsan

POST /myServlet?name=liuhao HTTP/1.1

tomcat處理請求時根據Content-Length進行讀取,是不會讀到第二個請求的,如果沒有Content-Length的話也就沒有請求體,請求頭和下一個請求有空行,也不會讀取。

拆包

拆包的處理方式大致相同就是數據沒有讀取完成就等

請求行拆包

POST /myServlet?name=liuh

請求行拆包,請求行結束的標志是換行符,如果沒有收到換行符,表示請求行沒有解析完,這個時候會重新監聽讀事件(使用java nio selector),之前的數據會放到buffer中緩存。

請求頭拆包

POST /myServlet?name=liuhao HTTP/1.1

Content-Type:

請求頭拆包,請求頭結束的標志是空行,如果沒有只有換行符的空行,表示請求行沒有解析完,這個時候會重新監聽讀事件(使用java nio selector),之前的數據會放到buffer中緩存。

請求體拆包

POST /myServlet HTTP/1.1

Content-Length: 13

Connection: keep-alive

 

name=

請求體拆包,請求體結束的標志是數據讀取足夠的字節數,如果讀取不夠,會阻塞的讀取數據直到讀取成功或超時報錯。

源碼閱讀指南

將tomcat的源碼導入到IDE,然后從架構和原理來了解tomcat,之后可以通過閱讀其他博客來了解源碼,最后自己在IDE中查看相關源碼,如果看的吃力,可以debug來看,如果想看拆包解包的源碼,可以用postman發送一個完整的http請求,然后使用telnet來進行拆包粘包測試,也可以寫一個client來測試,不過有一點要注意,telnet每次回車時會將\n傳過去,需要在debug的時候去除,如果寫一個client的話也要注意這一點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM