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上等待连接,读取传入的消息并发送响应。客户端连接到服务器,发送消息并打印服务器的响应。
与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))}
服务器从任何客户端读取消息并发送响应。客户端发送消息并等待响应。
并发允许同时处理多个客户端。
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.28at.com/showinfo-26-17249-0.htmlGo 语言高级网络编程
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 如何精确控制 asyncio 中并发运行的多个任务
下一篇: 如何将Docker的构建时间减少40%