記一次關于content-length有意思的排查

一、 項目背景

? ? ?一個物聯(lián)網項目,公司要求降低硬件成本,真可謂窮公司練技術,硬件資源有限制,最終技術選型使用單片機,因資源受限,硬件sdk中沒有現(xiàn)成的http可使用,因此,最終嵌軟同學直接在TCP socket基礎上,構造了Http請求頭,仿造http與物聯(lián)網平臺進行交互。

? ? 因此,有意思的事情發(fā)生了,嵌軟同學仿造http的過程如下:

1、初始化tcp client,然后構造http請求,通過tcp send發(fā)送http請求,接著recv等待對端的返回;

2、收到recv報文之后,讀取整個response報文,然后轉化為string,從string中匹配content-length字段,從而獲取response的body體大小。

看似一切正常,而且嵌軟同學之前也這么做過,為啥這次就不行了那,一切都是chunk(這里就不解釋啥是chunk了,不知的同學自行百度吧)搞的鬼,有的時候server會使用chunk方式進行數據返回,chunk模式下,是可以不存在content-length字段的(嚴格上來說是沒有content-length),因此這種情況下,按照上面的流程就跑不通了。

二、content-length和chunk是如何工作的?

? ? 這里百度了一些文章,說是chunk和gzip有關,但是百思不得其解,沒有縷出來兩者的關聯(lián)關系,實驗了一些demo,請求和返回頭里都含有gzip的壓縮方式,但是content-lenght字段還是存在,所以,索性認為沒有必然聯(lián)系。

? ? 再繼續(xù)百度了下,說是chunk和keep-alive相關,看到這我想是因為http1.1支持了連接服用,因此才支持了chunk,但是并不是說一旦開啟了keep-alive所有交互都是chunk模式,事實自己也寫了個小demo試了下,確實如此。

?繼續(xù)百度之旅,最后看到chunk和flush函數有關,正常我們server端在返回數據的時候,是使用write函數,而write函數并不是直接給用戶返回數據,而是先降數據寫回緩沖區(qū),直到連接close之前,會先將緩沖區(qū)的數據buffer發(fā)送過去,然后close連接。而flash函數則是手動將緩沖區(qū)的數據發(fā)送到客戶端,然后server端可以繼續(xù)將數據寫到緩沖區(qū),然后再調用flush函數,而還是之前的那一個連接(我想這也是之前百度到的一些文章說chunk和keepalive有關的原因吧),這樣收到的傳輸方式就是chunk的方式。而我們調用write函數,然后等到hander結束,close連接之前發(fā)送數據這個流程,也就是我們說的非chunk方式吧(除buff中數據超過buff大小的情況)。

三、demo驗證

? ? 這里采用golang代碼進行了過程驗證。

1、使用gin router寫了一個簡單的請求,如下:

????r :=gin.Default()

????r.GET("/ping", func(c *gin.Context) {

????????c.JSON(200, gin.H{

????????????"message":"pong",

? ? ????? })

})

r.Run()

請求結果如下所示:

2、修改flush發(fā)送數據方式,如下:

????r :=gin.Default()

????r.GET("/ping", func(c *gin.Context) {

????w := c.Writer

????flusher, ok := w.(http.Flusher)

? ? if !ok {

????????panic("expected http.ResponseWriter to be an http.Flusher")

????}

????fmt.Fprintf(w,string("hello chunk!"))

????flusher.Flush()

? ?})

r.Run()

結果如下圖:

四、總結

? ?1、通過理論+實驗來看,chunk和keepalive有關系,chunk是基于keekalive基礎實現(xiàn)的,但是他們倆者之間并不是必然的關系。

? ? 2、server端如果不想采取chunk方式回復數據,以免有些客戶端對chunk支持性不好,通過server端可以對傳輸方式進行控制,比如通過避免使用flush函數回復數據的方式。

? ? 3、至于其他語言例如java如何控制傳輸方式,后面我們再完善補充,多謝。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容