一、通過socket我們模擬請求網易
package main; import ( "net" "log" "io/ioutil" "fmt" ) func chkError(err error) { if err != nil { log.Fatal(err); } } func main() { //我們模擬請求網易的服務器 //ResolveTCPAddr用於獲取一個TCPAddr //net參數是"tcp4"、"tcp6"、"tcp" //addr表示域名或IP地址加端口號 tcpaddr, err := net.ResolveTCPAddr("tcp4", "www.163.com:80"); chkError(err); //DialTCP建立一個TCP連接 //net參數是"tcp4"、"tcp6"、"tcp" //laddr表示本機地址,一般設為nil //raddr表示遠程地址 tcpconn, err2 := net.DialTCP("tcp", nil, tcpaddr); chkError(err2); //向tcpconn中寫入數據 _, err3 := tcpconn.Write([]byte("GET / HTTP/1.1 \r\n\r\n")); chkError(err3); //讀取tcpconn中的所有數據 data, err4 := ioutil.ReadAll(tcpconn); chkError(err4); //打印出數據 fmt.Println(string(data)); }
二、通過socket創建簡單的服務端
package main; import ( "net" "log" ) func chkError(err error) { if err != nil { log.Fatal(err); } } func main() { //創建一個TCP服務端 tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080"); chkError(err); //監聽端口 tcplisten, err2 := net.ListenTCP("tcp", tcpaddr); chkError(err2); //死循環的處理客戶端請求 for { //等待客戶的連接 //注意這里是無法並發處理多個請求的 conn, err3 := tcplisten.Accept(); //如果有錯誤直接跳過 if err3 != nil { continue; } //向客戶端發送數據,並關閉連接 conn.Write([]byte("hello,client \r\n")); conn.Close(); } }
通過xshell的telnet方法測試。
三、改進上面的代碼,使用goroutine來處理用戶的請求
package main; import ( "log" "net" "time" ) func chkError(err error) { if err != nil { log.Fatal(err); } } //單獨處理客戶端的請求 func clientHandle(conn net.Conn) { defer conn.Close(); conn.Write([]byte("hello " + time.Now().String())); } func main() { //創建一個TCP服務端 tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080"); chkError(err); //監聽端口 tcplisten, err2 := net.ListenTCP("tcp", tcpaddr); chkError(err2); //死循環的處理客戶端請求 for { //等待客戶的連接 conn, err3 := tcplisten.Accept(); //如果有錯誤直接跳過 if err3 != nil { continue; } //通過goroutine來處理用戶的請求 go clientHandle(conn); } }
四、連續的處理客戶端發送的請求,根據cmd命令不同,返回不同數據。
package main; import ( "net" "time" "log" "strings" ) func chkError(err error) { if err != nil { log.Fatal(err); } } //單獨處理客戶端的請求 func clientHandle(conn net.Conn) { //設置當客戶端3分鍾內無數據請求時,自動關閉conn conn.SetReadDeadline(time.Now().Add(time.Minute * 3)); defer conn.Close(); //循環的處理客戶的請求 for { data := make([]byte, 256); //從conn中讀取數據 n, err := conn.Read(data); //如果讀取數據大小為0或出錯則退出 if n == 0 || err != nil { break; } //去掉兩端空白字符 cmd := strings.TrimSpace(string(data[0:n])); //發送給客戶端的數據 rep := ""; if(cmd == "string") { rep = "hello,client \r\n"; } else if (cmd == "time") { rep = time.Now().Format("2006-01-02 15:04:05"); } //發送數據 conn.Write([]byte(rep)); } } func main() { tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080"); chkError(err); tcplisten, err2 := net.ListenTCP("tcp", tcpaddr); chkError(err2); for { conn, err3 := tcplisten.Accept(); if err3 != nil { continue; } go clientHandle(conn); } }