一 socket编程
1.1 服务器代码
package main
import ( "fmt" "log" "net" "strings" )
func dealConn(conn net.Conn) {
defer conn.Close()
ipAddr := conn.RemoteAddr().String() fmt.Println(ipAddr, "连接成功")
buf := make([]byte, 1024)
for { n, err := conn.Read(buf) if err != nil { fmt.Println(err) return } result := buf[:n] fmt.Printf("接收到数据来自[%s]==>[%d]:%s\n", ipAddr, n, string(result)) if "exit" == string(result) { fmt.Println(ipAddr, "退出连接") return }
conn.Write([]byte(strings.ToUpper(string(result)))) } }
func main() { listenner, err := net.Listen("tcp", "127.0.0.1:8000") if err != nil { log.Fatal(err) }
defer listenner.Close()
for { conn, err := listenner.Accept() if err != nil { log.Println(err) continue }
go dealConn(conn) } }
|
1.2 客服端代码
package main
import ( "fmt" "log" "net" )
func main() { conn, err := net.Dial("tcp", "127.0.0.1:8000") if err != nil { log.Fatal(err) return }
defer conn.Close()
buf := make([]byte, 1024) for { fmt.Printf("请输入发送的内容:") fmt.Scan(&buf) fmt.Printf("发送的内容:%s\n", string(buf))
conn.Write(buf)
n, err := conn.Read(buf) if err != nil { fmt.Println(err) return }
result := buf[:n] fmt.Printf("接收到数据[%d]:%s\n", n, string(result)) } }
|
二 HTTP编程
2.1 HTTP报文浅析
2.1.1 请求报文格式
服务器测试代码:
package main
import ( "fmt" "log" "net" )
func main() { listenner, err := net.Listen("tcp", "127.0.0.1:8000") if err != nil { log.Fatal(err) }
defer listenner.Close()
conn, err := listenner.Accept() if err != nil { log.Println(err) return }
defer conn.Close()
ipAddr := conn.RemoteAddr().String() fmt.Println(ipAddr, "连接成功")
buf := make([]byte, 4096)
n, err := conn.Read(buf) if err != nil { fmt.Println(err) return }
result := buf[:n] fmt.Printf("接收到数据来自[%s]==>:\n%s\n", ipAddr, string(result)) }
|
浏览器输入url地址:
http://localhost:8000/
服务器端运行打印结果如下:
C:/Users/qingteng/Desktop/aa/src/src.exe [C:/Users/qingteng/Desktop/aa/src] 127.0.0.1:34680 连接成功 接收到数据来自[127.0.0.1:34680]==>: GET / HTTP/1.1 Host: localhost:8000 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 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 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: Hm_lvt_b15e599ba57327dec9b15e0680fa81fc=1596812405,1598105048,1598707525
成功: 进程退出代码 0.
|
2.1.2 响应报文格式
服务器示例代码:
package main
import ( "fmt" "net/http" )
func myHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "hello world") }
func main() { http.HandleFunc("/go", myHandler)
http.ListenAndServe("127.0.0.1:8000", nil) }
|
2.2 HTTP编程
Go语言标准库内建提供了net/http包,涵盖了HTTP客户端和服务端的具体实现。使用net/http
包,我们可以很方便地编写HTTP客户端或服务端的程序。
2.2.1 http服务端
HTTP服务端示例代码:
package main
import ( "fmt" "net/http" )
func myHandler(w http.ResponseWriter, r *http.Request) { fmt.Println(r.RemoteAddr, "连接成功") fmt.Println("method = ", r.Method) fmt.Println("url = ", r.URL.Path) fmt.Println("header = ", r.Header) fmt.Println("body = ", r.Body)
w.Write([]byte("hello go")) }
func main() { http.HandleFunc("/go", myHandler)
http.ListenAndServe("127.0.0.1:9000", nil) }
|
在浏览器里输入
http://localhost:9000/go
即可看到结果
2.2.2 客户端
package main
import ( "fmt" "io" "log" "net/http" )
func main() {
resp, err := http.Get("http://127.0.0.1:8000/go") if err != nil { log.Println(err) return }
defer resp.Body.Close()
fmt.Println("header = ", resp.Header) fmt.Printf("resp status %s\nstatusCode %d\n", resp.Status, resp.StatusCode) fmt.Printf("body type = %T\n", resp.Body)
buf := make([]byte, 2048) var tmp string
for { n, err := resp.Body.Read(buf) if err != nil && err != io.EOF { fmt.Println(err) return }
if n == 0 { fmt.Println("读取内容结束") break } tmp += string(buf[:n]) }
fmt.Println("buf = ", string(tmp)) }
|