搜尋

首頁  >  問答  >  主體

php - socket接受一個http請求,read到哪裡就可以判定請求結束了呢?

用go想做一個http代理的小工具:

   func main() {
        listener, err := net.Listen("tcp", ":8080")
        if err != nil {
            log.Panic(err)
        }
        for {
            client, err := listener.Accept()
            if err != nil {
                log.Panic(err)
            }
            go handleClientRequest(client)
        }
    }
    
    func handleClientRequest(client net.Conn) {
        if client == nil {
            return
        }
        defer client.Close()
    
        var buf [1024]byte
        n, err := client.Read(buf[:])
        if err != nil {
            log.Println(err)
            return
        }
        fmt.Println("recv msg:", string(buf[0:n]))
    }

1024個位元組不一定夠,一定要有個結束標誌吧?

三叔三叔2706 天前1035

全部回覆(1)我來回復

  • 三叔

    三叔2017-07-03 11:42:16

    Http協定是建立在TCP協定基礎之上的,當瀏覽器需要從伺服器取得網頁資料的時候,會發出一次Http請求。 Http會透過TCP建立起一個到伺服器的連線通道,當本次請求所需的資料完畢後,Http會立即將TCP連線中斷

    TCP協定透過發送FIN包來釋放連接,所以FIN包就是結束標誌,也就是說一直接收到連接斷開就接收完了。

    但是

    隨著時間的推移,html頁面變得複雜了,裡面可能嵌入了很多圖片,這時候每次訪問圖片都需要建立一次tcp連接就顯得低效了。因此Keep-Alive被提出用來解決效率低的問題。從HTTP/1.1起,預設都開啟了Keep-Alive,保持連線特性,簡單地說,當一個網頁開啟完成後,客戶端和伺服器之間用於傳輸HTTP資料的TCP連線不會關閉,如果客戶端再次造訪這個伺服器上的網頁,會繼續使用這一條已經建立的連接Keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的伺服器軟體(如Apache)中設定這個時間。雖然這裡使用TCP連接保持了一段時間,但是這個時間是有限範圍的,到了時間點依然是會關閉的,所以我們還把其看做是每次連接完成後就會關閉。

    那麼開啟了Keep-Alive之後該如何判斷結束呢?
    其實,HTTP頭有個content-length,這就是HTTP包內文長度了

    當然也有沒有content-length的情況,那就是使用了分塊編碼(chunked encoding)資料是分成一系列的區塊來傳送的,每區塊都有大小說明。即使伺服器在生成首部的時候不知道整個實體的大小(通常是因為實體是動態生成的),仍然可以使用分塊編碼傳輸若干已知大小的塊。

    編碼使用若干個Chunk組成,由一個標示長度為0的chunk結束,每個Chunk有兩部分組成,第一部分是該Chunk的長度和長度單位(一般不寫),第二部分就是指定長度的內容,每個部分以CRLF(全名為carriage
    return/line feed 回車換行)隔開。在最後一個長度為0的Chunk中的內容是稱為footer的內容,是一些附加的Header資訊(通常可以直接忽略)。

    另外HTTP訊息標頭與訊息正文之間透過CRLF(回車換行),rnrn來分隔

    回覆
    0
  • 取消回覆