解釋伺服器的幾個概念:
- Request 使用者請求的資訊
- Response 伺服器返回的資訊
- Conn 使用者的每次請求連結
- 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 //用戶端能接受的mineAccept-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.