欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang使用Gin框架實(shí)現(xiàn)http分塊傳輸

 更新時(shí)間:2023年05月16日 09:09:13   作者:Go學(xué)堂  
這篇文章主要為大家詳細(xì)介紹了Golang中如何使用Gin框架實(shí)現(xiàn)http分塊傳輸功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考一下

今天,跟大家聊聊gin框架中是如何實(shí)現(xiàn)分片輸出的。主要分以下4點(diǎn):

  • 分片輸出的效果圖
  • gin實(shí)現(xiàn)分片傳輸代碼
  • http分片傳輸?shù)幕A(chǔ):transfer-encoding
  • gin實(shí)現(xiàn)分片傳輸原理

效果圖

首先看下分片輸出的效果圖:

gin分片傳輸實(shí)現(xiàn)代碼

上面的效果圖中,網(wǎng)頁(yè)中的內(nèi)容不斷的輸出。在gin中是主要是利用了Flush函數(shù)實(shí)現(xiàn)的。如下代碼:

package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.GET("/test_stream", func(c *gin.Context) {
		w := c.Writer
		header := w.Header()
		header.Set("Content-Type", "text/html")
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`
			<html>
					<body>
		`))
		w.(http.Flusher).Flush()

        // 這里對(duì)每次循環(huán)輸出都進(jìn)行Flush刷新輸出
		for i := 0; i < 10; i++ {
			w.Write([]byte(fmt.Sprintf(`
				<h3>%d</h3>
			`, i)))
			//w.Flush()
			w.(http.Flusher).Flush()
			time.Sleep(time.Duration(1)*time.Second)
		}
        
		w.Write([]byte(`
			
					</body>
			</html>
		`))
		w.(http.Flusher).Flush()
	})

	r.Run("127.0.0.1:8080")
}

這里主要就是利用了第22行中的w.(http.Flusher).Flush()。 這里的Flush本質(zhì)上就是將Write的內(nèi)容立即輸出到客戶端的意思。

那么,為什么通過(guò)Flush就能實(shí)現(xiàn)上述效果呢?

分塊傳輸?shù)幕A(chǔ):http的 transfer-encoding:chunked 協(xié)議

分塊傳輸?shù)幕A(chǔ)就是http中的transfer-encoding:chunked協(xié)議。在http響應(yīng)報(bào)文中用頭字段“Transfer-Encoding: chunked”,表示響應(yīng)中的body不是一次性發(fā)送完畢,而是分成了許多的塊(chunk)逐個(gè)發(fā)送,直到發(fā)送完畢。

分塊傳輸?shù)木幋a規(guī)則如下: 1)每個(gè)分塊包含兩個(gè)部分,<長(zhǎng)度頭>和&<數(shù)據(jù)塊> 2) <長(zhǎng)度頭>是以 CRLF(回車(chē)換行,即\r\n)結(jié)尾的一行明文,用 16 進(jìn)制數(shù)字表示長(zhǎng)度 3) <數(shù)據(jù)塊>緊跟在<長(zhǎng)度頭>后,最后也用 CRLF 結(jié)尾,但數(shù)據(jù)不包含 CRLF 4)最后用一個(gè)長(zhǎng)度為 0 的塊表示數(shù)據(jù)傳輸結(jié)束,即“0\r\n\r\n”。

為什么通過(guò)Flush函數(shù)就能實(shí)現(xiàn)分塊傳輸

到了本篇的核心部分了,為什么在gin中通過(guò)Flush函數(shù)就能實(shí)現(xiàn)分塊傳輸了呢?首先,在gin框架中正常的輸出是通過(guò)Context.Writer.Write函數(shù)進(jìn)行輸出的。而Writer是net/http包中的response對(duì)象,該response對(duì)象包含了本次http的連接對(duì)象conn。以下是從Context.Writer對(duì)象到conn對(duì)象的一個(gè)層級(jí)關(guān)系,如下:

Context.Writer對(duì)象指向了response對(duì)象,response對(duì)象中包含一個(gè)緩沖的Writer對(duì)象w,w的底層輸出對(duì)象時(shí)chunkWriter對(duì)象cw,cw又指向了本次的http連接對(duì)象response.conn。

那么,基于這個(gè)層級(jí)結(jié)構(gòu),Context.Writer.Write的寫(xiě)入過(guò)程如下:

我們簡(jiǎn)化一些,就是Context.Writer.Write先將內(nèi)容寫(xiě)入到緩沖區(qū)w中,然后等本次請(qǐng)求邏輯處理完畢,再調(diào)用緩存區(qū)w的Flush功能,將緩沖區(qū)w中的內(nèi)容寫(xiě)入到cw中,然后調(diào)用cw的flush功能,這時(shí)就寫(xiě)入了http的響應(yīng)頭Content-Length為寫(xiě)入數(shù)據(jù)的長(zhǎng)度,并且將內(nèi)容通過(guò)conn.bufw.flush輸出給客戶端。

簡(jiǎn)化一下gin的輸出過(guò)程:內(nèi)容先寫(xiě)入到緩沖區(qū),最后將緩沖區(qū)的內(nèi)容一次性全部輸出給客戶端。

劃重點(diǎn),Content-Length頭部的輸出是和分塊傳輸?shù)闹饕獏^(qū)別。

接下來(lái)再看分塊輸出。

其實(shí)現(xiàn)的思想就是通過(guò)http的Transfer-Encoding: chunked頭告訴客戶端,服務(wù)端的內(nèi)容要分塊傳輸了。然后服務(wù)端就將內(nèi)容先寫(xiě)入緩沖區(qū),然后立即使用Flush函數(shù)將緩沖區(qū)的內(nèi)容輸出到客戶端。這就是一個(gè)塊的輸出。然后依次循環(huán)寫(xiě)入,F(xiàn)lush刷新輸出這個(gè)過(guò)程。

下圖是gin中分塊傳輸?shù)牧鞒虉D:

在分塊輸出的時(shí)候,在response.cw.flush階段,可以判定到該請(qǐng)求還未處理完畢(在net/http包中,本次請(qǐng)求處理完畢才會(huì)調(diào)用一個(gè)finishRequest的函數(shù)以標(biāo)識(shí)本次請(qǐng)求處理完畢),所以會(huì)自動(dòng)寫(xiě)入一個(gè)http的頭信息: Transfer-Encoding: chunked。當(dāng)客戶端收到該響應(yīng)時(shí),檢測(cè)到header中的chunked,就表示本次響應(yīng)還未結(jié)束,會(huì)繼續(xù)接收后續(xù)的響應(yīng)內(nèi)容。

簡(jiǎn)化一下gin的分塊傳輸流程如下:

總結(jié)

當(dāng)輸出內(nèi)容太大時(shí),就可以使用分塊傳輸?shù)姆绞健7謮K傳輸是基于http的Transfer-Encoding: chunked協(xié)議進(jìn)行的。當(dāng)客戶端接收到該響應(yīng)頭時(shí),就知道服務(wù)端的內(nèi)容還沒(méi)有傳輸完,不能關(guān)閉本次http連接。另一方面,gin框架通過(guò)Flush函數(shù)將緩沖區(qū)的內(nèi)容及時(shí)輸出來(lái)實(shí)現(xiàn)分塊傳輸。

到此這篇關(guān)于Golang使用Gin框架實(shí)現(xiàn)http分塊傳輸?shù)奈恼戮徒榻B到這了,更多相關(guān)Golang http分塊傳輸內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go語(yǔ)言中基本數(shù)據(jù)類(lèi)型及應(yīng)用快速了解

    go語(yǔ)言中基本數(shù)據(jù)類(lèi)型及應(yīng)用快速了解

    這篇文章主要為大家介紹了go語(yǔ)言中基本數(shù)據(jù)類(lèi)型應(yīng)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • goland最新激活辦法

    goland最新激活辦法

    這篇文章主要介紹了goland最新激活辦法,激活方法真的超級(jí)簡(jiǎn)單,只需要把腳本內(nèi)容復(fù)制到對(duì)應(yīng)文件,并運(yùn)行該腳本就可以了,需要的朋友可以參考下
    2021-12-12
  • golang程序使用alpine編譯出最小arm鏡像實(shí)現(xiàn)

    golang程序使用alpine編譯出最小arm鏡像實(shí)現(xiàn)

    這篇文章主要為大家介紹了golang程序使用alpine編譯出最小arm鏡像,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • golang進(jìn)程內(nèi)存控制避免docker內(nèi)oom

    golang進(jìn)程內(nèi)存控制避免docker內(nèi)oom

    這篇文章主要為大家介紹了golang進(jìn)程內(nèi)存控制避免docker內(nèi)oom示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • golang 連接mongoDB的方法示例

    golang 連接mongoDB的方法示例

    這篇文章主要介紹了golang 連接mongoDB的方法示例,詳細(xì)的介紹了golang的基礎(chǔ)知識(shí)和連接mongoDB的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Go語(yǔ)言題解LeetCode705設(shè)計(jì)哈希集合

    Go語(yǔ)言題解LeetCode705設(shè)計(jì)哈希集合

    這篇文章主要為大家介紹了Go語(yǔ)言題解LeetCode705設(shè)計(jì)哈希集合,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Go語(yǔ)言中Goroutine的設(shè)置方式

    Go語(yǔ)言中Goroutine的設(shè)置方式

    這篇文章介紹了Go語(yǔ)言中Goroutine的設(shè)置方式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • 淺析golang的依賴注入

    淺析golang的依賴注入

    這篇文章主要介紹了淺析golang的依賴注入,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • 修改并編譯golang源碼的操作步驟

    修改并編譯golang源碼的操作步驟

    這篇文章主要介紹了修改并編譯golang源碼的操作步驟,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-07-07
  • Golang操作excel的方法

    Golang操作excel的方法

    這篇文章主要介紹了Golang操作excel的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10

最新評(píng)論