HTTP编程
概述
Web工作原理

请求包和响应包
客户端 --请求包-> 服务器
客户端 <-响应包-- 服务器
http请求包格式
监听请求
package main
import (
"fmt"
"net"
)
func main(){
// 监听
listener, err := net.Listen("tcp", ":8000")
if err!=nil{
fmt.Println("Listen err = ", err)
return
}
// 阻塞,等待用户的连接
conn, err1 := listener.Accept()
if err1 != nil {
fmt.Println("Accept err1 = ", err1)
return
}
defer conn.Close()
// 接收客户端的数据
buf := make([]byte, 1024*4)
n, err2 := conn.Read(buf)
if n==0 {
fmt.Println("Accept err2 = ", err2)
return
}
fmt.Printf("#####\n%v######", string(buf[:n]))
}
请求报文内容
#####
GET / HTTP/1.1
Host: 127.0.0.1:8000
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
######%
服务器监听响应
package main
import(
"fmt"
"net/http"
)
// w:给客户端回复数据
// r:读取客户端发送的数据
func myHander(w http.ResponseWriter, r *http.Request){
fmt.Fprintln(w, "hello world")
}
// 服务端编写业务逻辑处理程序
func main(){
// 注册处理函数,有用户连接自动调用指定的处理函数
http.HandleFunc("/go", myHander) // 注册处理程序,回调函数
// 监听绑定,在指定地址监听,开启一个http
http.ListenAndServe("127.0.0.1:8000", nil)
}
输出响应内容
package main
import (
"fmt"
"net"
)
func main(){
// 主动连接服务器
conn, err := net.Dial("tcp", ":8000")
if err != nil {
fmt.Println("dial err = ", err)
return
}
defer conn.Close()
requestBuf := "GET /go HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36\r\nSec-Fetch-User: ?1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nSec-Fetch-Site: none\r\nSec-Fetch-Mode: navigate\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n\r\n"
// 先发请求包,服务器才会回响应包
conn.Write([]byte(requestBuf))
// 接收服务器回复的响应包
buf := make([]byte, 1024*4)
n, err1 := conn.Read(buf)
if n == 0 {
fmt.Println("Read err = ", err1)
return
}
// 打印响应报文
fmt.Printf("####\n%v####", string(buf[:n]))
}
响应报文内容
####
HTTP/1.1 200 OK
Date: Sat, 15 Feb 2020 09:18:14 GMT
Content-Length: 12
Content-Type: text/plain; charset=utf-8
hello world
####%
响应失败
####
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Sat, 15 Feb 2020 09:19:33 GMT
Content-Length: 19
404 page not found
####%
获取客户端一些信息
// w:给客户端回复数据
// req:读取客户端发送的数据
func HandConn(w http.ResponseWriter, req *http.Request) {
fmt.Println("req.Method = ", req.Method)
fmt.Println("req.URL = ", req.URL)
fmt.Println("req.Header = ", req.Header)
fmt.Println("req.Body = ", req.Body)
w.Write([]byte("hello go")) // 给客户端回复数据
}
http客户端编程
package main
import (
"fmt"
"net/http"
)
func main(){
resp, err := http.Get("http://127.0.0.1:8000")
if err != nil {
fmt.Println("http.Get err = ", err)
return
}
defer resp.Body.Close()
fmt.Println("Status = ", resp.Status)
fmt.Println("StatusCode = ", resp.StatusCode)
fmt.Println("Header = ", resp.Header)
// fmt.Println("Body = ", resp.Body)
buf := make([]byte, 4*1024)
var tmp string
for{
n, err := resp.Body.Read(buf)
if n == 0 {
fmt.Println("read err = ", err)
break
}
tmp += string(buf[:n])
}
fmt.Println("tmp = ", tmp)
}