国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Go】五、網(wǎng)絡(luò)編程

這篇具有很好參考價值的文章主要介紹了【Go】五、網(wǎng)絡(luò)編程。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

網(wǎng)絡(luò)編程

1、互聯(lián)網(wǎng)協(xié)議介紹

2、Socket編程

2.1、socket圖解

?????????Socket是BSD UNIX進(jìn)程通信機(jī)制,通常也稱為“套接字”,用于描述IP地址和端口,是一個通信鏈的句柄。Socket可以理解為TCP/IP網(wǎng)絡(luò)API,程序猿可以用其來開發(fā)TCP/IP網(wǎng)絡(luò)上的應(yīng)用。電腦上運行的應(yīng)用程序通常通過“套接字”向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答請求。

1、socket又稱套接字,應(yīng)用程序通過套接字向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答網(wǎng)絡(luò)請求

2、常用的socket類型有兩種:流式socket和數(shù)據(jù)報socket,流式是一種面向連接(TCP)、數(shù)據(jù)報是一種無連接(UDP)

3、TCP:比較靠譜、面向連接、比較慢

4、UDP:不大靠譜、無連接、比較快

2.2、TCP編程

1、TCP協(xié)議:TCP/IP協(xié)議即傳輸控制協(xié)議/網(wǎng)絡(luò)協(xié)議,是一種面向連接、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,因為是面向連接的協(xié)議,數(shù)據(jù)像流水一樣傳輸,存在粘包的問題

2、TCP服務(wù)端:一個TCP服務(wù)端可以同時連接多個客戶端,例如世界各地的用戶使用自己電腦上的瀏覽器訪問淘寶網(wǎng),因為Go語言中創(chuàng)建多個goroutine實現(xiàn)并發(fā)非常方便和高效,所以我們可以每建立一次連接久創(chuàng)建一個goroutine去處理。

處理流程:1)監(jiān)聽端口;2)接收客戶端請求建立連接;3)創(chuàng)建goroutine處理鏈接

使用Go語言的net包實現(xiàn)TCP服務(wù)端代碼
// tcp/server/main.go
// TCP server端
// 處理函數(shù)
func process(conn net.Conn) {
    defer conn.Close() // 關(guān)閉連接:為什么要寫在前面,避免忘記,defer使得我們可以在方法最后執(zhí)行關(guān)閉鏈接操作
    for {
        reader := bufio.NewReader(conn)
        var buf [128]byte
        n, err := reader.Read(buf[:]) // 讀取數(shù)據(jù)
        if err != nil {
            fmt.Println("read from client failed, err:", err)
            break
        }
        recvStr := string(buf[:n])
        fmt.Println("收到client端發(fā)來的數(shù)據(jù):", recvStr)
        conn.Write([]byte(recvStr)) // 發(fā)送數(shù)據(jù)
    }
}

func main() {
	  listen, err := net.Listen("tcp", "127.0.0.1:20000") // 對127.0.0.1:20000地址進(jìn)行監(jiān)聽
    if err != nil {
        fmt.Println("listen failed, err:", err)
        return
    }
    for { // 保持鏈接
        conn, err := listen.Accept() // 建立連接
        if err != nil {
            fmt.Println("accept failed, err:", err)
            continue
        }
        go process(conn) // 啟動一個goroutine處理連接
    }
}

3、TCP客戶端

1)建立與服務(wù)端的連接;2)進(jìn)行數(shù)據(jù)收發(fā);3)關(guān)閉連接
// tcp/client/main.go
// 客戶端
func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:20000")
    if err != nil {
        fmt.Println("err :", err)
        return
    }
    defer conn.Close() // 關(guān)閉連接
    inputReader := bufio.NewReader(os.Stdin) // 獲取鍵盤輸入的數(shù)據(jù)
    for {
        input, _ := inputReader.ReadString('\n') // 讀取用戶輸入
        inputInfo := strings.Trim(input, "\r\n")
        if strings.ToUpper(inputInfo) == "Q" { // 如果輸入q就退出
            return
        }
        _, err = conn.Write([]byte(inputInfo)) // 發(fā)送數(shù)據(jù)
        if err != nil {
            return
        }
        buf := [512]byte{}
        n, err := conn.Read(buf[:])
        if err != nil {
            fmt.Println("recv failed, err:", err)
            return
        }
        fmt.Println(string(buf[:n]))
    }
}

2.3、UDP編程

1、UDP協(xié)議:用戶數(shù)據(jù)報協(xié)議,是OSI參考模型中一種無連接的傳輸層協(xié)議,不需要建立連接就能直接進(jìn)行數(shù)據(jù)發(fā)送和接收,屬于不可靠,沒有時序的通信,但UDP協(xié)議的實時性比較好,通常用于視頻直播相關(guān)領(lǐng)域。

2、UDP服務(wù)端

// UDP/server/main.go

// UDP server端
func main() {
    listen, err := net.ListenUDP("udp", &net.UDPAddr{
        IP:   net.IPv4(0, 0, 0, 0),
        Port: 30000,
    })
    if err != nil {
        fmt.Println("listen failed, err:", err)
        return
    }
    defer listen.Close()
    for {
        var data [1024]byte
        n, addr, err := listen.ReadFromUDP(data[:]) // 接收數(shù)據(jù)
        if err != nil {
            fmt.Println("read udp failed, err:", err)
            continue
        }
        fmt.Printf("data:%v addr:%v count:%v\n", string(data[:n]), addr, n)
        _, err = listen.WriteToUDP(data[:n], addr) // 發(fā)送數(shù)據(jù)
        if err != nil {
            fmt.Println("write to udp failed, err:", err)
            continue
        }
    }
}

3、UDP客戶端

// UDP 客戶端
func main() {
    socket, err := net.DialUDP("udp", nil, &net.UDPAddr{
        IP:   net.IPv4(0, 0, 0, 0),
        Port: 30000,
    })
    if err != nil {
        fmt.Println("連接服務(wù)端失敗,err:", err)
        return
    }
    defer socket.Close()
    sendData := []byte("Hello server")
    _, err = socket.Write(sendData) // 發(fā)送數(shù)據(jù)
    if err != nil {
        fmt.Println("發(fā)送數(shù)據(jù)失敗,err:", err)
        return
    }
    data := make([]byte, 4096)
    n, remoteAddr, err := socket.ReadFromUDP(data) // 接收數(shù)據(jù)
    if err != nil {
        fmt.Println("接收數(shù)據(jù)失敗,err:", err)
        return
    }
    fmt.Printf("recv:%v addr:%v count:%v\n", string(data[:n]), remoteAddr, n)
}

2.4、粘包(?沒有詳細(xì)看代碼,但是大概知道怎么實現(xiàn))

1、舉一個例子:

?????????1)服務(wù)端代碼

// go_base/server/main.go
// 同上面TCP編程的服務(wù)端代碼

func process(conn net.Conn) {
    defer conn.Close()
    reader := bufio.NewReader(conn)
    var buf [1024]byte
    for {
        n, err := reader.Read(buf[:])
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Println("read from client failed, err:", err)
            break
        }
        recvStr := string(buf[:n])
        fmt.Println("收到client發(fā)來的數(shù)據(jù):", recvStr)
    }
}

func main() {

    listen, err := net.Listen("tcp", "127.0.0.1:30000")
    if err != nil {
        fmt.Println("listen failed, err:", err)
        return
    }
    defer listen.Close()
    for {
        conn, err := listen.Accept()
        if err != nil {
            fmt.Println("accept failed, err:", err)
            continue
        }
        go process(conn)
    }
}

????????2)客戶端代碼

// socket_stick/client/main.go

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:30000")
    if err != nil {
        fmt.Println("dial failed, err", err)
        return
    }
    defer conn.Close()
    for i := 0; i < 20; i++ {
        msg := `Hello, Hello. How are you?` // 往這個倆節(jié)寫入20條msg
        conn.Write([]byte(msg))
    }
}

?????????3)結(jié)果:不會按照我們最初的想法,客戶端一次發(fā)送20條信息,服務(wù)端一次性接收,多條數(shù)據(jù)粘在一起

收到client發(fā)來的數(shù)據(jù): Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?
收到client發(fā)來的數(shù)據(jù): Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?
收到client發(fā)來的數(shù)據(jù): Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?
收到client發(fā)來的數(shù)據(jù): Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?
收到client發(fā)來的數(shù)據(jù): Hello, Hello. How are you?Hello, Hello. How are you?

2、為什么會出現(xiàn)粘包?

?????????1)tcp數(shù)據(jù)傳輸模式是流模式,在保持長連接的時候可以進(jìn)行多次收和發(fā),可能發(fā)生在接收方、也可能發(fā)生在接收端

?????????2)我們提交一段數(shù)據(jù)給TCP發(fā)送的時候,TCP沒有立即發(fā)送此段數(shù)據(jù),而是等待一小段時間看看是否還有要發(fā)送的數(shù)據(jù),若有則會把這兩段數(shù)據(jù)發(fā)送出去

?????????3)接受端不及時接收數(shù)據(jù),導(dǎo)致粘包

3、解決辦法:關(guān)鍵在于接收方不知道傳輸?shù)臄?shù)據(jù)包大小,因此我們可以對數(shù)據(jù)包進(jìn)行封包和拆包的操作(??建議手敲一遍,不要只是看)

?????????封包:給一段數(shù)據(jù)加上包頭,這樣以來數(shù)據(jù)包久分為包頭和包體兩個部分內(nèi)容,包頭長度是固定的,并且存儲了包體的長度,根據(jù)包頭長度以及包頭中包體長度的變量就可以正確的拆分出一個完整的數(shù)據(jù)包。 => 自己定一個協(xié)議(數(shù)據(jù)包前4個字節(jié)為包頭,里面存儲的是發(fā)送的數(shù)據(jù)長度)

// 1、編碼和解碼
// 文件位置gobase/proto/proto.go
package proto

import (
	"bufio"
	"bytes"
	"encoding/binary"
)

// Encode Encode消息編碼
func Encode(message string) ([]byte, error) {
	// 讀取消息長度,轉(zhuǎn)換成為int32類型(4個字節(jié))
	var length  = int32(len(message))
	var pkg = new(bytes.Buffer)
	// 寫入消息頭
	err := binary.Write(pkg, binary.LittleEndian, length)
	if err != nil {
		return nil, err
	}
	// 寫入消息實體
	err = binary.Write(pkg, binary.LittleEndian, []byte(message))
	if err != nil {
		return nil, err
	}
	return pkg.Bytes(), nil
}

// Decode 解碼消息
func Decode(reader *bufio.Reader) (string, error) {
	// 讀取消息長度
	lengthByte, _ := reader.Peek(4)
	lengthBuffer := bytes.NewBuffer(lengthByte)
	var length int32
	err := binary.Read(lengthBuffer, binary.LittleEndian, &length)
	if err != nil {
		return "", err
	}
	// Buffered返回緩沖中現(xiàn)有可讀取的字節(jié)數(shù)
	if int32(reader.Buffered()) < length+4 {
		return "", err
	}
	// 讀取真正的消息數(shù)據(jù)
	pack := make([]byte, int(4+length))
	_, err = reader.Read(pack)
	if err != nil {
		return "", err
	}
	return string(pack[4:]), nil
}


// 2、服務(wù)端代碼
// 文件位置gobase/server/main.go
package main

import (
	"../proto"
	"bufio"
	"fmt"
	"io"
	"net"
)

func process(conn net.Conn) {
	defer conn.Close()
	reader := bufio.NewReader(conn)
	for {
		msg, err := proto.Decode(reader)
		if err == io.EOF {
			return
		}
		if err != nil {
			fmt.Println("decode msg faild, err = ", err)
			return
		}
		fmt.Println("收到client發(fā)來的數(shù)據(jù)", msg)
	}
}

func main() {
	listen, err := net.Listen("tcp", "127.0.0.1:30000")
	if err != nil {
		fmt.Println("listen faild, err = ", err)
		return
	}
	defer listen.Close()
	for {
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("accept failed, err = ", err)
			continue
		}
		go process(conn)
	}
}

// 3、客戶端代碼
// 文件位置gobase/client/main.go
package main

import (
	"../proto"
	"fmt"
	"net"
)

func main() {
	conn, err := net.Dial("tcp","127.0.0.1:30000")
	if err != nil {
		fmt.Println("dail failed, err = " , err)
		return
	}
	defer conn.Close()
	for i := 0; i < 6; i++ {
		msg := "hello,go"
		data, err := proto.Encode(msg)
		if err != nil {
			fmt.Println("encode msg failed, err", err)
			return
		}
		conn.Write(data)
	}
}



// 運行結(jié)果
收到client發(fā)來的數(shù)據(jù) hello,go
收到client發(fā)來的數(shù)據(jù) hello,go
收到client發(fā)來的數(shù)據(jù) hello,go
收到client發(fā)來的數(shù)據(jù) hello,go
收到client發(fā)來的數(shù)據(jù) hello,go
收到client發(fā)來的數(shù)據(jù) hello,go

3、Http編程

1、web工作流程

1、客戶機(jī)通過TCP/IP協(xié)議建立服務(wù)器到TCP連接
2、客戶端向服務(wù)器發(fā)送HTTP協(xié)議請求包,請求服務(wù)器里的資源文檔
3、服務(wù)器向客戶機(jī)發(fā)送HTTP協(xié)議應(yīng)答包,如果請求的資源包含有動態(tài)語言的內(nèi)容,那么服務(wù)器會調(diào)用動態(tài)語言的解釋引擎負(fù)責(zé)處理“動態(tài)內(nèi)容”,并將處理得到的數(shù)據(jù)返回給客戶端
4、客戶機(jī)與服務(wù)器斷開,由客戶端解釋HTML文檔,在客戶端屏幕上渲染圖形結(jié)果

2、HTTP協(xié)議

?????????稱為超文本傳輸協(xié)議,是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議,它詳細(xì)的規(guī)定了瀏覽器和萬維網(wǎng)服務(wù)器之間相互通信的規(guī)則,通過因特網(wǎng)傳送萬維網(wǎng)文檔的數(shù)據(jù)傳送協(xié)議;HTTP協(xié)議通常承載于TCP協(xié)議之上

4、WebSocket編程

1、webScoket編程是什么?

1、WebSocket是一種單個TCP連接上進(jìn)行全雙工通信的協(xié)議
2、WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù)
3、WebSocket API中,瀏覽器和服務(wù)器只需要一次握手,二者之間就可以直接創(chuàng)建持久性連接,并進(jìn)行簡單雙向數(shù)據(jù)傳輸
4、需要安裝第三方包: go get -u -v github.com/gorilla/websocket -> 11之后的版本 使用 go install

2、這個有一個聊天室的小例子,后續(xù)可以單獨的出一塊提供大家理解(todo)文章來源地址http://www.zghlxwxcb.cn/news/detail-438288.html

到了這里,關(guān)于【Go】五、網(wǎng)絡(luò)編程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Go 網(wǎng)絡(luò)編程

    Go 網(wǎng)絡(luò)編程

    在tcp/ip模型的應(yīng)用層和傳輸層中,基于傳輸層抽象了一系列接口,而此接口即用于我們的實際開發(fā)中為socket(套接字)。 socket也叫套接字, 是為了方便程序員進(jìn)行網(wǎng)絡(luò)開發(fā)而被設(shè)計出來的編程接口. socket在OSI七層模型中是屬于傳輸層(TCP,UDP協(xié)議)之上 的一個抽象接口.Go語言的標(biāo)準(zhǔn)

    2024年02月08日
    瀏覽(20)
  • GO語言網(wǎng)絡(luò)編程(并發(fā)編程)runtime包

    1.1.1. runtime.Gosched() 讓出CPU時間片,重新等待安排任務(wù)(大概意思就是本來計劃的好好的周末出去燒烤,但是你媽讓你去相親,兩種情況第一就是你相親速度非???,見面就黃不耽誤你繼續(xù)燒烤,第二種情況就是你相親速度特別慢,見面就是你儂我儂的,耽誤了燒烤,但是還饞就

    2024年02月09日
    瀏覽(122)
  • Go語言網(wǎng)絡(luò)編程(socket編程)TCP

    TCP協(xié)議 TCP/IP(Transmission Control Protocol/Internet Protocol) 即傳輸控制協(xié)議/網(wǎng)間協(xié)議,是一種面向連接(連接導(dǎo)向)的、可靠的、基于字節(jié)流的傳輸層(Transport layer)通信協(xié)議,因為是面向連接的協(xié)議,數(shù)據(jù)像水流一樣傳輸,會存在黏包問題。 TCP服務(wù)端 一個TCP服務(wù)端可以同時連接很

    2024年02月09日
    瀏覽(98)
  • Go語言網(wǎng)絡(luò)編程(socket編程)TCP粘包

    服務(wù)端代碼如下: 客戶端代碼如下: 將上面的代碼保存后,分別編譯。先啟動服務(wù)端再啟動客戶端,可以看到服務(wù)端輸出結(jié)果如下: 收到client發(fā)來的數(shù)據(jù): Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you? 收到client發(fā)來的數(shù)

    2024年02月09日
    瀏覽(96)
  • GO語言網(wǎng)絡(luò)編程(并發(fā)編程)并發(fā)介紹,Goroutine

    GO語言網(wǎng)絡(luò)編程(并發(fā)編程)并發(fā)介紹,Goroutine

    進(jìn)程和線程 并發(fā)和并行 協(xié)程和線程 協(xié)程:獨立的??臻g,共享堆空間,調(diào)度由用戶自己控制,本質(zhì)上有點類似于用戶級線程,這些用戶級線程的調(diào)度也是自己實現(xiàn)的。 線程:一個線程上可以跑多個協(xié)程,協(xié)程是輕量級的線程。 goroutine 只是由官方實現(xiàn)的超級\\\"線程池\\\"。 每個

    2024年02月09日
    瀏覽(92)
  • Go語言網(wǎng)絡(luò)編程介紹以及案例運用

    1. 基本概念 TCP 和 UDP : Go語言支持TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報協(xié)議)。TCP提供可靠的、面向連接的通信,而UDP提供無連接的快速數(shù)據(jù)傳輸。 并發(fā) : Go語言的并發(fā)模型是通過goroutines實現(xiàn)的。每個網(wǎng)絡(luò)請求都可以在自己的goroutine中處理,實現(xiàn)高效的并發(fā)。 Channels : 用于

    2024年01月25日
    瀏覽(105)
  • Go語言的網(wǎng)絡(luò)編程與HTTP服務(wù)

    Go語言(Golang)是Google開發(fā)的一種靜態(tài)類型、垃圾回收、并發(fā)簡單的編程語言。Go語言的設(shè)計目標(biāo)是讓程序員更容易編寫并發(fā)程序,并在多核處理器上充分發(fā)揮性能。Go語言的網(wǎng)絡(luò)編程和HTTP服務(wù)是其核心功能之一,可以輕松地構(gòu)建高性能、可擴(kuò)展的網(wǎng)絡(luò)應(yīng)用程序。 在本文中,我們

    2024年02月19日
    瀏覽(100)
  • Go語言的網(wǎng)絡(luò)編程與TCP_IP

    Go語言是一種現(xiàn)代的編程語言,由Google的Robert Griesemer、Rob Pike和Ken Thompson在2009年開發(fā)。Go語言的設(shè)計目標(biāo)是簡單、高效、可擴(kuò)展和易于使用。它具有弱類型、垃圾回收、并發(fā)性和原生支持的網(wǎng)絡(luò)編程。Go語言的網(wǎng)絡(luò)編程是其強(qiáng)大功能之一,它使得開發(fā)者可以輕松地編寫高性能的

    2024年02月22日
    瀏覽(115)
  • Go語言實戰(zhàn):網(wǎng)絡(luò)編程與TCP_UDP

    Go語言是一種現(xiàn)代的編程語言,由Google的Robert Griesemer、Rob Pike和Ken Thompson于2009年開發(fā)。Go語言的設(shè)計目標(biāo)是簡單、高效、可擴(kuò)展和易于使用。它具有垃圾回收、類型安全、并發(fā)性能等優(yōu)點。Go語言的網(wǎng)絡(luò)編程庫 net 包提供了TCP/UDP的實現(xiàn),使得開發(fā)者可以輕松地編寫網(wǎng)絡(luò)應(yīng)用程序

    2024年02月21日
    瀏覽(96)
  • 【Java轉(zhuǎn)Go】快速上手學(xué)習(xí)筆記(六)之網(wǎng)絡(luò)編程篇一

    【Java轉(zhuǎn)Go】快速上手學(xué)習(xí)筆記(六)之網(wǎng)絡(luò)編程篇一

    go往期文章筆記: 【Java轉(zhuǎn)Go】快速上手學(xué)習(xí)筆記(一)之環(huán)境安裝篇 【Java轉(zhuǎn)Go】快速上手學(xué)習(xí)筆記(二)之基礎(chǔ)篇一 【Java轉(zhuǎn)Go】快速上手學(xué)習(xí)筆記(三)之基礎(chǔ)篇二 【Java轉(zhuǎn)Go】快速上手學(xué)習(xí)筆記(四)之基礎(chǔ)篇三 【Java轉(zhuǎn)Go】快速上手學(xué)習(xí)筆記(五)之Gorm篇 這篇記的是網(wǎng)絡(luò)

    2024年02月11日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包