1.Golang的Http原始碼閱讀(http協議)
阿新 • • 發佈:2018-12-03
解釋伺服器的幾個概念:
1. Request 使用者請求的資訊
2. Response 伺服器返回的資訊
3. Conn 使用者的每次請求連結
4. Handler 處理請求和生成返回資訊的處理邏輯
先寫個小程式看看
func MyConn() {
// 監聽9090埠
listener, _ := net.Listen("tcp", "localhost:9090")
defer listener.Close()
// 建立使用者請求的連線
conn, _ := listener.Accept()
defer conn.Close()
// 讀取Request的內容
buff := make([]byte, 10000)
len, _ := conn.Read(buff)
fmt.Fprintln(os.Stdout, string(buff[:len]))
}
對於程式碼,要解釋的是讀取conn的內容,你可以把conn看做是資料流,先看下Golang中的原始碼,先不去掉註釋,Golang的註釋真的是簡單好懂,看完了註釋,你就應該能理解Conn是什麼了。
// Multiple goroutines may invoke methods on a Conn simultaneously.
type Conn interface {
// Read reads data from the connection.
// Read can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetReadDeadline.
Read(b []byte) (n int, err error)
// Write writes data to the connection.
// Write can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
Write(b []byte) (n int, err error)
// Close closes the connection.
// Any blocked Read or Write operations will be unblocked and return errors.
Close() error
// LocalAddr returns the local network address.
LocalAddr() Addr
// RemoteAddr returns the remote network address.
RemoteAddr() Addr
// SetDeadline sets the read and write deadlines associated
// with the connection. It is equivalent to calling both
// SetReadDeadline and SetWriteDeadline.
//
// A deadline is an absolute time after which I/O operations
// fail with a timeout (see type Error) instead of
// blocking. The deadline applies to all future and pending
// I/O, not just the immediately following call to Read or
// Write. After a deadline has been exceeded, the connection
// can be refreshed by setting a deadline in the future.
//
// An idle timeout can be implemented by repeatedly extending
// the deadline after successful Read or Write calls.
//
// A zero value for t means I/O operations will not time out.
SetDeadline(t time.Time) error
// SetReadDeadline sets the deadline for future Read calls
// and any currently-blocked Read call.
// A zero value for t means Read will not time out.
SetReadDeadline(t time.Time) error
// SetWriteDeadline sets the deadline for future Write calls
// and any currently-blocked Write call.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
// A zero value for t means Write will not time out.
SetWriteDeadline(t time.Time) error
}
在瀏覽器上輸入 localhost:9090 ,按下回車鍵,你的命令列會有一下的內容
GET / HTTP/1.1 //請求行:請求方法(GET), 請求的URL(/),HTTP協議(HTTP/1.1)
Host: localhost:9090 //伺服器主機名
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0 //瀏覽器資訊
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 //客戶端能接受的mine
Accept-Language: zh-CN,en-US;q=0.7,en;q=0.3 //請求頭允許客戶端宣告它可以理解的自然語言,以及優先選擇的區域方言
Accept-Encoding: gzip, deflate //是否支援流壓縮
Connection: keep-alive //控制當前傳輸結束後是否保持網路連線
Upgrade-Insecure-Requests: 1 //Sends a signal to the server expressing the client’s preference for an encrypted and authenticated response, and that it can successfully handle the upgrade-insecure-requests directive.
//空行,分割請求頭和訊息體
//訊息體,POST傳遞
關於請求頭資料的更詳細的資料可以看https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
目前比較重要的是這個資料的第一行
GET / HTTP/1.1
如果你在位址列輸入的網址是 localhost:9090/hello ,第一行會是這樣
GET /hello HTTP/1.1
對於伺服器,首先需要知道協議(是GET還是POST),然後需要知道你想要訪問的地址。對於瞭解MVC的同學肯定了解Controller,在Golang中,也存在類似的路由機制,你可以將訪問的URL跟Handler一一對應(感覺是不是有點像鍵值對),根據請求的URL就可以對請求內容進行操作並返回了,先寫到這裡,下一節再想想怎麼寫Handler.