Chunk就是将大文件分成块,一个块对应着一个Http请求,然后会对每个Http进行编号,然后在接收方重组。

    正常的Http请求都是客户端请求,服务器返回然后就结束了。而Chunk不会,是会一直等待服务器多次发送数据,发送数据完成后才会结束。

    怎么判断一个Http是不是Chunk?
    通过Header中的Transfer-Encoding = Chunked

    怎么判断是否传输结束?
    每个Http中的body中分为 length 和 chunked data 。length 就是传输的数据长度,chunked data就是实际的传输数据。二者通过换行符分隔。当收到length = 0的http时,就说明传输完成了。
    image.png

    demo

    1. package main
    2. import (
    3. "fmt"
    4. "io"
    5. "log"
    6. "net/http"
    7. "time"
    8. )
    9. func httpServer() {
    10. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    11. flusher, ok := w.(http.Flusher)
    12. if !ok {
    13. panic("expected http.ResponseWriter to be an http.Flusher")
    14. }
    15. for i := 1; i <= 10; i++ {
    16. w.Write([]byte(fmt.Sprintf("rsp-%d", i)))
    17. flusher.Flush() // Trigger "chunked" encoding and send a chunk...
    18. time.Sleep(1 * time.Second)
    19. }
    20. })
    21. log.Print("Listening on localhost:8080")
    22. log.Fatal(http.ListenAndServe(":8080", nil))
    23. }
    24. func httpClien() {
    25. resp, err := http.Get("http://localhost:8080")
    26. if err != nil {
    27. // handle error
    28. }
    29. fmt.Println(resp.Header)
    30. defer resp.Body.Close()
    31. var buf = make([]byte, 40960)
    32. for {
    33. n, err := resp.Body.Read(buf)
    34. fmt.Println(n, err)
    35. if n != 0 || err != io.EOF { // simplified
    36. fmt.Println(string(buf[:n]))
    37. }
    38. time.Sleep(1 * time.Second)
    39. }
    40. }
    41. func main() {
    42. go httpServer()
    43. go httpClien()
    44. time.Sleep(100 * time.Second)
    45. }