1)概要:ブロック送信
これは「分割統治」または「分割統治」の考え方であり、HTTPプロトコルでは「チャンク」転送コーディングとして具体化されています。HTTP応答メッセージでは、ヘッダーフィールド「Transfer-Encoding:chunked」を使用して、応答の本文が一度に送信されるのではなく、多数のチャンクに分割され、送信が完了するまで1つずつ送信されることを示します。
2)ブロック送信のコーディング規則
1)各ブロックには<lengthheader>と<datablock>の2つの部分が含まれます
。2)<length header>は、16進数でCRLF(キャリッジリターン、ラインフィード、つまり\ r \ n)で終わるプレーンテキストの行です。数値は長さを示します;
3)<長さヘッダー>の直後の<データブロック>で、最後にCRLFで終わりますが、データにはCRLFが含まれていません;
4)最後に、長さ0のブロックを使用して終わりを示しますデータ送信の、つまり「0 \ r \ n \ r \ n」。
3)golangコード
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func main() {
server := &APIServer{
engine: gin.Default(),
}
server.registryApi()
server.engine.Run(":38080")
}
type APIServer struct {
engine *gin.Engine
}
func (s *APIServer) registryApi() {
registryStream(s.engine)
}
func registryStream(engine *gin.Engine) {
engine.GET("/stream", func(ctx *gin.Context) {
w := ctx.Writer
header := w.Header()
//在响应头添加分块传输的头字段Transfer-Encoding: chunked
header.Set("Transfer-Encoding", "chunked")
header.Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
//Flush()方法,好比服务端在往一个文件中写了数据,浏览器会看见此文件的内容在不断地增加。
w.Write([]byte(`
<html>
<body>
`))
w.(http.Flusher).Flush()
for i:=0 ;i<10; i++{
w.Write([]byte(fmt.Sprintf(`
<h1>%d</h1>
`,i)))
w.(http.Flusher).Flush()
time.Sleep(time.Duration(1) * time.Second)
}
w.Write([]byte(`
</body>
</html>
`))
w.(http.Flusher).Flush()
})
}
4)ブラウザテスト
ブラウザインターフェイスが徐々に0、1、2、3 ...を受信していることがわかります。
注:ブラウザーから表示されるメッセージは、ブラウザーによって処理され、ブロックの<lengthヘッダー>情報が削除されるため、完全なメッセージではありません。