1. 程式人生 > >1.Golang的Http原始碼閱讀(http協議)

1.Golang的Http原始碼閱讀(http協議)

解釋伺服器的幾個概念:
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.