本文包括udp客戶端、udp服務器、tcp客戶端、tcp服務器、http客戶端、http服務器
net包提供了可移植的網絡I/O接口,包括TCP/IP、UDP、域名解析和Unix域socket。
主要實現(xiàn)3個步驟:初始化+發(fā)送數(shù)據(jù)+接收數(shù)據(jù)。
udp客戶端
初始化+發(fā)送數(shù)據(jù)+接收數(shù)據(jù)
package main
import (
? ? "os"
? ? "fmt"
? ? "net"
//? "io"
)
func main() {
? ? conn, err := net.Dial("udp", "127.0.0.1:11110")
? ? defer conn.Close()
? ? if err != nil {
? ? ? ? os.Exit(1)?
? ? }
? ? conn.Write([]byte("Hello world!"))?
? ? fmt.Println("send msg")
? ? var msg [20]byte
? ? conn.Read(msg[0:])
? ? fmt.Println("msg is", string(msg[0:10]))
}
udp服務端
初始化+監(jiān)聽+接收數(shù)據(jù)+發(fā)送數(shù)據(jù)
package main
import (
? ? "os"
? ? "fmt"
? ? "net"
)
func checkError(err error){
? ? if? err != nil {
? ? ? ? fmt.Println("Error: %s", err.Error())
? ? ? ? os.Exit(1)?
? ? }
}
func recvUDPMsg(conn *net.UDPConn){
? ? var buf [20]byte
? ? n, raddr, err := conn.ReadFromUDP(buf[0:])
? ? if err != nil {
? ? ? ? return?
? ? }
? ? fmt.Println("msg is ", string(buf[0:n]))
? ? //WriteToUDP
? ? //func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error)
? ? _, err = conn.WriteToUDP([]byte("nice to see u"), raddr)
? ? checkError(err)
}
func main() {
? ? udp_addr, err := net.ResolveUDPAddr("udp", ":11110")
? ? checkError(err)
? ? conn, err := net.ListenUDP("udp", udp_addr)
? ? defer conn.Close()
? ? checkError(err)
? ? //go recvUDPMsg(conn)
? ? recvUDPMsg(conn)
}
tcp客戶端
初始化+發(fā)送數(shù)據(jù)+接收數(shù)據(jù)
package?main
import?(
????"fmt"
????"io/ioutil"
????"net"
)
func?main() {
????var?remoteAddress, _ = net.ResolveTCPAddr("tcp4",?"127.0.0.1:8080")?//生成一個net.TcpAddr對像。
????var?conn, err = net.DialTCP("tcp4", nil, remoteAddress)?//傳入?yún)f(xié)議,本機地址(傳了nil),遠程地址,獲取連接。
????if?err != nil {?//如果連接失敗。則返回。
????????fmt.Println("連接出錯:", err)
????????return
????}
????var?remoteIpAddress = conn.RemoteAddr()?//獲取IP地址的方法。
????fmt.Println("遠程IP地址是:", remoteIpAddress)?//輸出:220.181.111.188:80
????var?localIPAddress = conn.LocalAddr()
????fmt.Println("本地IP地址是:", localIPAddress)?//輸出:192.168.1.9:45712
????conn.Write([]byte("hello"))?//嘗試發(fā)送些信息。
? fmt.Println("發(fā)送完畢: ")
????//var reciverBuffer []byte????????????????????? //定義一個空切片,用于接收結果。
????//len, err := conn.Read(reciverBuffer) //返回接收到的字節(jié)數(shù)。
? ?fmt.Println("等待接收: ")
????bys, err := ioutil.ReadAll(conn)?//接收消息。
????if?err != nil {
????????fmt.Println("接收出錯:", err)
????}
????//var reciveText = string(reciverBuffer[0:len])
????var?reciveText = string(bys)
????fmt.Println(reciveText)
????conn.Close()?//關閉連接
????fmt.Println("程序結束")
}
tcp服務器
初始化+監(jiān)聽tcp+接收連接+接收數(shù)據(jù)+發(fā)送數(shù)據(jù)
package?main
import?(
????"fmt"
????"io/ioutil"
????"net"
)
func?main() {
????localAddress, _ := net.ResolveTCPAddr("tcp4",?"127.0.0.1:8080")?//定義一個本機IP和端口。
????var?tcpListener, err = net.ListenTCP("tcp", localAddress)?//在剛定義好的地址上進監(jiān)聽請求。
????if?err != nil {
????????fmt.Println("監(jiān)聽出錯:", err)
????????return
????}
????defer?func() {?//擔心return之前忘記關閉連接,因此在defer中先約定好關它。
????????tcpListener.Close()
????}()
????fmt.Println("正在等待連接...")
????var?conn, err2 = tcpListener.AcceptTCP()?//接受連接。
????if?err2 != nil {
????????fmt.Println("接受連接失?。?, err2)
????????return
????}
????var?remoteAddr = conn.RemoteAddr()?//獲取連接到的對像的IP地址。
????fmt.Println("接受到一個連接:", remoteAddr)
????fmt.Println("正在讀取消息...")
????var?bys, _ = ioutil.ReadAll(conn)?//讀取對方發(fā)來的內容。
????fmt.Println("接收到客戶端的消息:", string(bys))
????conn.Write([]byte("hello, Nice to meet you, my name is SongXingzhu"))?//嘗試發(fā)送消息。
????conn.Close()?//關閉連接。
? }
http客戶端
發(fā)送請求+解析返回結果
package main
import?(?
????"fmt"
????"io/ioutil"
????"log"
????"net/http"
????"net/url"
)?
func?main() {?
????//resp, _ := doGet("http://www.baidu.com")?
????//resp, _ := doPost("http://www.baidu.com", "application/json;charset=utf-8")?
????resp, _ := doPostForm("http://www.baidu.com")?
????defer?resp.Body.Close()?//go的特殊語法,main函數(shù)執(zhí)行結束前會執(zhí)行resp.Body.Close()?
????fmt.Println(resp.StatusCode)?//有http的響應碼輸出?
????if?resp.StatusCode == http.StatusOK {?//如果響應碼為200?
????????body, err := ioutil.ReadAll(resp.Body)?//把響應的body讀出?
????????if?err != nil {?//如果有異常?
????????????fmt.Println(err)?//把異常打印?
????????????log.Fatal(err)?//日志?
????????}?
????????fmt.Println(string(body))?//把響應的文本輸出到console?
????}?
}?
/**?
以GET的方式請求?
**/
func?doGet(url string) (r *http.Response, e error) {?
????resp, err := http.Get(url)?
????if?err != nil {?
????????fmt.Println(resp.StatusCode)?
????????fmt.Println(err)?
????????log.Fatal(err)?
????}?
????return?resp, err?
}?
/**?
以POST的方式請求?
**/
func?doPost(url string, bodyType string) (r *http.Response, e error) {?
????resp, err := http.Post(url, bodyType, nil)?
????if?err != nil {?
????????fmt.Println(resp.StatusCode)?
????????fmt.Println(err)?
????????log.Fatal(err)?
????}?
????return?resp, err?
}?
/**?
以Post表單的方式請求?
**/
func?doPostForm(urlStr string) (r *http.Response, e error) {?
????v := url.Values{"method": {"get"},?"id": {"1"}}?
????v.Add("name1",?"1")?
????v.Add("name2",?"2")?
????resp, err := http.PostForm(urlStr, v)?
????if?err != nil {?
????????fmt.Println(resp.StatusCode)?
????????fmt.Println(err)?
????????log.Fatal(err)?
????}?
? ? return?resp, err?
}
func httpDo() {
? ? client := &http.Client{}
? ? req, err := http.NewRequest("POST", "http://www.01happy.com/demo/accept.php", strings.NewReader("name=cjb"))
? ? if err != nil {
? ? ? ? // handle error
? ? }
? ? req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
? ? req.Header.Set("Cookie", "name=anny")
? ? resp, err := client.Do(req)
? ? defer resp.Body.Close()
? ? body, err := ioutil.ReadAll(resp.Body)
? ? if err != nil {
? ? ? ? // handle error
? ? }
? ? fmt.Println(string(body))
}
發(fā)送請求+解析返回結果
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
// response, _ := http.Get("http://www.baidu.com")
// defer response.Body.Close()
// body, _ := ioutil.ReadAll(response.Body)
// fmt.Println(string(body))
client := &http.Client{}
request, _ := http.NewRequest("GET", "http://192.168.1.189:4000/bye", nil)
request.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
request.Header.Set("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3")
request.Header.Set("Accept-Encoding", "gzip,deflate,sdch")
request.Header.Set("Accept-Language", "zh-CN,zh;q=0.8")
request.Header.Set("Cache-Control", "max-age=0")
request.Header.Set("Connection", "keep-alive")
response, _ := client.Do(request)
if response.StatusCode == 200 {
body, _ := ioutil.ReadAll(response.Body)
bodystr := string(body)
fmt.Println(bodystr)
}
}
http服務器
注冊服務+監(jiān)聽請求
package main
import (
? ? "fmt"
? ? "net/http"
? ? "reflect"
? ? "strings"
)
func hello(w http.ResponseWriter, req *http.Request) {
? ? w.Write([]byte("Hello"))
}
type Handlers struct {
}
func (h *Handlers) ResAction(w http.ResponseWriter, req *http.Request) {
? ? fmt.Println("res")
? ? w.Write([]byte("res"))
}
func say(w http.ResponseWriter, req *http.Request) {
? ? pathInfo := strings.Trim(req.URL.Path, "/")
? ? fmt.Println("pathInfo:", pathInfo)
? ? parts := strings.Split(pathInfo, "/")
? ? fmt.Println("parts:", parts)
? ? var action = "ResAction"
? ? fmt.Println(strings.Join(parts, "|"))
? ? if len(parts) > 1 {
? ? ? ? fmt.Println("22222222")
? ? ? ? action = strings.Title(parts[1]) + "Action"
? ? }
? ? fmt.Println("action:", action)
? ? handle := &Handlers{}
? ? controller := reflect.ValueOf(handle)
? ? method := controller.MethodByName(action)
? ? r := reflect.ValueOf(req)
? ? wr := reflect.ValueOf(w)
? ? method.Call([]reflect.Value{wr, r})
}
func main() {
? ? http.HandleFunc("/hello", hello)
? ? http.Handle("/handle/", http.HandlerFunc(say))
? ? http.ListenAndServe(":8001", nil)
? ? //select {} //阻塞進程
}
注冊服務+監(jiān)聽請求
package main
import (
? ? "log"
? ? "net/http"
)
func main() {
? ? //注冊一個函數(shù),響應某一個路由
? ? http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
? ? ? ? w.Write([]byte("hello this is version 1!!"))
? ? })
? ? //這里可以單獨寫一個函數(shù)傳遞給當前的路由
? ? http.HandleFunc("/bye", SayBye)
? ? log.Println("Start version v1")
? ? log.Fatal(http.ListenAndServe(":4000", nil))
}
func SayBye(w http.ResponseWriter, r *http.Request) {
? ? w.Write([]byte("Bye bye, this is version v1"))
? ? log.Println("saybye")
? ? //進行一個流式傳遞,將字符串轉換為byte類型
}