用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個位元組不一定夠,一定要有個結束標誌吧?
三叔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
來分隔