Go(Golang)中的網絡編程具有易用性、強大性和樂趣。本指南深入探討了網絡編程的復雜性,涵蓋了協議、TCP/UDP 套接字、并發等方面的內容,并附有詳細的注釋。
TCP 服務器和客戶端示例演示了TCP通信的基礎。
服務器:
package mainimport ( "net" "fmt")func main() { // Listen on TCP port 8080 on all available unicast and // any unicast IP addresses. listen, err := net.Listen("tcp", ":8080") if err != nil { fmt.Println(err) return } defer listen.Close() // Infinite loop to handle incoming connections for { conn, err := listen.Accept() if err != nil { fmt.Println(err) continue } // Launch a new goroutine to handle the connection go handleConnection(conn) }}func handleConnection(conn net.Conn) { defer conn.Close() buffer := make([]byte, 1024) // Read the incoming connection into the buffer. _, err := conn.Read(buffer) if err != nil { fmt.Println(err) return } // Send a response back to the client. conn.Write([]byte("Received: " + string(buffer)))}
客戶端:
package mainimport ( "net" "fmt")func main() { // Connect to the server at localhost on port 8080. conn, err := net.Dial("tcp", "localhost:8080") if err != nil { fmt.Println(err) return } defer conn.Close() // Send a message to the server. conn.Write([]byte("Hello, server!")) buffer := make([]byte, 1024) // Read the response from the server. conn.Read(buffer) fmt.Println(string(buffer))}
服務器在端口8080上等待連接,讀取傳入的消息并發送響應??蛻舳诉B接到服務器,發送消息并打印服務器的響應。
與TCP不同,UDP是無連接的。以下是UDP服務器和客戶端的實現。
服務器:
package mainimport ( "net" "fmt")func main() { // Listen for incoming UDP packets on port 8080. conn, err := net.ListenPacket("udp", ":8080") if err != nil { fmt.Println(err) return } defer conn.Close() buffer := make([]byte, 1024) // Read the incoming packet data into the buffer. n, addr, err := conn.ReadFrom(buffer) if err != nil { fmt.Println(err) return } fmt.Println("Received: ", string(buffer[:n])) // Write a response to the client's address. conn.WriteTo([]byte("Message received!"), addr)}
客戶端:
package mainimport ( "net" "fmt")func main() { // Resolve the server's address. addr, err := net.ResolveUDPAddr("udp", "localhost:8080") if err != nil { fmt.Println(err) return } // Dial a connection to the resolved address. conn, err := net.DialUDP("udp", nil, addr) if err != nil { fmt.Println(err) return } defer conn.Close() // Write a message to the server. conn.Write([]byte("Hello, server!")) buffer := make([]byte, 1024) // Read the response from the server. conn.Read(buffer) fmt.Println(string(buffer))}
服務器從任何客戶端讀取消息并發送響應??蛻舳税l送消息并等待響應。
并發允許同時處理多個客戶端。
package mainimport ( "net" "fmt")func main() { // Listen on TCP port 8080. listener, err := net.Listen("tcp", ":8080") if err != nil { fmt.Println(err) return } defer listener.Close() for { // Accept a connection. conn, err := listener.Accept() if err != nil { fmt.Println(err) continue } // Handle the connection in a new goroutine. go handleConnection(conn) }}func handleConnection(conn net.Conn) { defer conn.Close() buffer := make([]byte, 1024) // Read the incoming connection. conn.Read(buffer) fmt.Println("Received:", string(buffer)) // Respond to the client. conn.Write([]byte("Message received!"))}
通過為每個連接使用新的 goroutine,多個客戶端可以同時連接。
Gorilla Mux 庫簡化了 HTTP 請求路由。
package mainimport ( "fmt" "github.com/gorilla/mux" "net/http")func main() { // Create a new router. r := mux.NewRouter() // Register a handler function for the root path. r.HandleFunc("/", homeHandler) http.ListenAndServe(":8080", r)}func homeHandler(w http.ResponseWriter, r *http.Request) { // Respond with a welcome message. fmt.Fprint(w, "Welcome to Home!")}
這段代碼設置了一個 HTTP 服務器,并為根路徑定義了一個處理函數。
實現 HTTPS 服務器可以確保安全通信。
package mainimport ( "net/http" "log")func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // Respond with a message. w.Write([]byte("Hello, this is an HTTPS server!")) }) // Use the cert.pem and key.pem files to secure the server. log.Fatal(http.ListenAndServeTLS(":8080", "cert.pem", "key.pem", nil))}
服務器使用 TLS(傳輸層安全性)來加密通信。
可以使用自定義的 TCP 協議進行專門的通信。
package mainimport ( "net" "strings")func main() { // Listen on TCP port 8080. listener, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } defer listener.Close() for { // Accept a connection. conn, err := listener.Accept() if err != nil { panic(err) } // Handle the connection in a new goroutine. go handleConnection(conn) }}func handleConnection(conn net.Conn) { defer conn.Close() buffer := make([]byte, 1024) // Read the incoming connection. conn.Read(buffer) // Process custom protocol command. cmd := strings.TrimSpace(string(buffer)) if cmd == "TIME" { conn.Write([]byte("The current time is: " + time.Now().String())) } else { conn.Write([]byte("Unknown command")) }}
這段代碼實現了一個簡單的自定義協議,當客戶端發送命令“TIME”時,它會回復當前時間。
WebSockets 提供了通過單一連接的實時全雙工通信。
package mainimport ( "github.com/gorilla/websocket" "net/http")var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024,}func handler(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { http.Error(w, "Could not open websocket connection", http.StatusBadRequest) return } defer conn.Close() for { messageType, p, err := conn.ReadMessage() if err != nil { return } // Echo the message back to the client. conn.WriteMessage(messageType, p) }}func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)}
WebSocket 服務器會將消息回傳給客戶端。
可以使用 context 包來管理連接超時。
package mainimport ( "context" "fmt" "net" "time")func main() { // Create a context with a timeout of 2 seconds ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() // Dialer using the context dialer := net.Dialer{} conn, err := dialer.DialContext(ctx, "tcp", "localhost:8080") if err != nil { panic(err) } buffer := make([]byte, 1024) _, err = conn.Read(buffer) if err == nil { fmt.Println("Received:", string(buffer)) } else { fmt.Println("Connection error:", err) }}
這段代碼為從連接讀取數據設置了兩秒的截止時間。
速率限制控制請求的速率。
package mainimport ( "golang.org/x/time/rate" "net/http" "time")// Define a rate limiter allowing two requests per second with a burst capacity of five.var limiter = rate.NewLimiter(2, 5)func handler(w http.ResponseWriter, r *http.Request) { // Check if request is allowed by the rate limiter. if !limiter.Allow() { http.Error(w, "Too Many Requests", http.StatusTooManyRequests) return } w.Write([]byte("Welcome!"))}func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)}
此示例使用速率限制器,將請求速率限制為每秒兩個請求,突發容量為五個。
本文鏈接:http://www.tebozhan.com/showinfo-26-17249-0.htmlGo 語言高級網絡編程
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 如何精確控制 asyncio 中并發運行的多個任務
下一篇: 如何將Docker的構建時間減少40%