請從github下載配套代碼: https://github.com/shuningzhang/learn_golang
電子書下載地址: https://u19702000.ctfile.com/dir/19702000-33357795-bb2f31/
由于HTTP協(xié)議本身就是基于TCP協(xié)議的徐裸,因此,在上一篇TCP通信的文章的基礎(chǔ)上,我們對服務(wù)端進行改造矾睦,可以很容易的將其改造成一個Web服務(wù)器。當(dāng)然同欠,這個Web服務(wù)器是非常簡單的淆衷,簡單到不能再簡單。本文Web服務(wù)的功能就是當(dāng)有瀏覽器訪問(發(fā)送請求)時捞附,給它返回一個簡單的字符串。
HTTP協(xié)議
在修改代碼之前您没,我們需要先了解一下什么是HTTP協(xié)議鸟召。HTTP協(xié)議的超文本傳輸協(xié)議(HyperText Transfer Protocol),它是基于TCP的應(yīng)用層協(xié)議氨鹏,它不關(guān)心數(shù)據(jù)傳輸?shù)募毠?jié)欧募,主要是用來規(guī)定客戶端和服務(wù)端的數(shù)據(jù)傳輸格式,最初是用來向客戶端傳輸HTML頁面的內(nèi)容仆抵。整個協(xié)議分為兩部分跟继,也就是請求報文和應(yīng)答報文。
其中镣丑,請求報文的格式如下:
圖1 請求報文格式
為了理解的更加清楚舔糖,我們看一個具體的例子。圖2是通過Wireshark抓的數(shù)據(jù)包莺匠,這個是請求一個網(wǎng)頁金吗。
圖2 HTTP請求數(shù)據(jù)包格式實例
上圖中第一行為開始行,方法為GET趣竣;URL為 /摇庙, 也就是根路徑;版本是HTTP/1.1期贫,后面換行回車是必須的跟匆。
后面幾行是首部行,包含連接方式通砍,瀏覽器類型玛臂,文本類型和編碼等等內(nèi)容。由于本文抓的GET請求沒有傳數(shù)據(jù)封孙,因此這里實體中沒有數(shù)據(jù)迹冤。值得注意的是,這里的報文其實都是字符串的形式虎忌,而且是明文泡徙,很容易理解。
響應(yīng)報文的格式與請求報文是類似的膜蠢,具體如圖3所示堪藐,大概了解就可以莉兰,本文就不再詳述了。
圖3 HTTP響應(yīng)報文
Web服務(wù)代碼
有了HTTP協(xié)議的知識礁竞,我們現(xiàn)在就可以開發(fā)一個Web服務(wù)器了糖荒。這個Web服務(wù)器很簡單,當(dāng)有瀏覽器發(fā)送請求時模捂,給瀏覽器回復(fù)一個“Hello World捶朵!”字符串。這時狂男,在瀏覽器上可以看到該字符串综看。下面是服務(wù)器端的代碼:
package main
import (
"fmt"
"net"
"os"
)
func main() {
/* 這里代碼與普通TCP服務(wù)端并沒有差異 */
service := ":8080"
tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
for {
fmt.Println("begin accept")
conn, err := listener.Accept()
if err != nil {
continue
}
buf := make([]byte,1024)
result, err := conn.Read(buf)
fmt.Println(result, string(buf))
/* 只有下面這個發(fā)送數(shù)據(jù)是有差異的,下面按照HTTP
* 協(xié)議發(fā)送數(shù)據(jù)岖食。 */
conn.Write([]byte("HTTP/1.1 200 OK\r\n" +
"Date: Mon, 27 Jul 2009 12:28:53 GMT\r\n" +
"Server: Nginx\r\n" +
"Content-Length: 12\r\n" +
"Content-Type: text/plain\r\n" +
"\r\n" +
"Hello World!"))
conn.Close()
}
}
func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr,
"Fatal error: %s", err.Error())
os.Exit(1)
}
}
這個只是針對上一篇文章的服務(wù)端做了一點修改红碑,程序代碼很簡單,這里就不做過多解釋了县耽。
測試驗證
運行服務(wù)端的程序句喷,然后用瀏覽器(任何瀏覽器镣典,火狐或者太陽花都行)訪問該服務(wù)器兔毙。此時可以看到在瀏覽器中有我們期望的內(nèi)容。瀏覽器截圖如下:
這里我們使用的是Go語言的net庫中比較原始的TCP方式實現(xiàn)的兄春。這個庫是一個非常強大的庫澎剥,除了上述內(nèi)容外,其實Go語言已經(jīng)實現(xiàn)了HTTP協(xié)議的庫赶舆。不過本文是為了讓大家學(xué)習(xí)Go語言編程哑姚,因此沒有直接使用該庫。
這個Web服務(wù)器是很嘈的芜茵,我們后面文章會一步一步的完善叙量,并帶領(lǐng)大家解除更多的Go語言的特性和開發(fā)庫。另外本文的源代碼可以通過github下載九串,可以私信作者绞佩,發(fā)送“go語言”就可以了。