網絡通信 udp+tcp+http

本文包括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類型

}


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 計算機網絡七層模型中,傳輸層有兩個重要的協(xié)議:(1)用戶數(shù)據(jù)報協(xié)議UDP (User Datagram Proto...
    Q南南南Q閱讀 1,868評論 0 3
  • 網絡由下往上分為物理層、數(shù)據(jù)鏈路層、網絡層、傳輸層、會話層、表示層和應用層。通過初步的了解,我知道IP協(xié)議對應于...
    木溪bo閱讀 248評論 0 0
  • 簡介 用簡單的話來定義tcpdump,就是:dump the traffic on a network,根據(jù)使用者...
    保川閱讀 6,088評論 1 13
  • 簡介 用簡單的話來定義tcpdump,就是:dump the traffic on a network,根據(jù)使用者...
    JasonShi6306421閱讀 1,357評論 0 1
  • 個人認為,Goodboy1881先生的TCP /IP 協(xié)議詳解學習博客系列博客是一部非常精彩的學習筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,200評論 0 8

友情鏈接更多精彩內容