30天学会Go–第5天 GO语言 网络编程
文章目录
- 30天学会Go--第5天 GO语言 网络编程
- 前言
- 一、Go 网络编程基础
- 1.1 网络通信协议
- 1.2 Socket 编程
- 1.2.1 IP 地址
- 1.2.2 端口号
- 1.2.3 Socket 的工作流程
- 二、TCP 编程
- 2.1 TCP 服务端
- 示例代码
- 2.2 TCP 客户端
- 示例代码
- 三、UDP 编程
- 3.1 UDP 服务端
- 示例代码
- 3.2 UDP 客户端
- 示例代码
- 四、HTTP 编程
- 4.1 HTTP 服务端
- 示例代码
- 4.2 HTTP 客户端
- 示例代码
- 五、总结
前言
网络编程是现代软件开发的重要组成部分,几乎所有的应用程序都需要通过网络进行通信。Go 语言内置了强大的 net
和 net/http
标准库,提供了简单易用且高效的网络编程支持。今天我们将学习如何使用 Go 进行网络编程,包括 TCP、UDP 和 HTTP 通信。
go语言官方编程指南:https://pkg.go.dev/stdopen in new window
go语言的官方文档学习笔记很全,推荐去官网学习
30天学会GO–第4天 GO语言 错误处理与文件操作:30天学会Go–第4天 GO语言 错误处理与文件操作-CSDN博客
一、Go 网络编程基础
在正式开始编写代码之前,先了解一些基础概念:
1.1 网络通信协议
- TCP(Transmission Control Protocol):面向连接的可靠传输协议,适用于需要保证数据完整性的场景,例如文件传输、聊天应用等。
- UDP(User Datagram Protocol):无连接的传输协议,速度快但不保证数据可靠性,适用于实时性要求高的场景,例如视频流、在线游戏等。
- HTTP(HyperText Transfer Protocol):基于 TCP 的应用层协议,主要用于 Web 开发和 RESTful API 通信。
1.2 Socket 编程
Socket 是网络通信的抽象接口,应用程序可以通过 Socket 发送和接收数据。Go 提供了 net
包来支持 Socket 编程。
对于 Socket 编程,你应该了解这些:
1.2.1 IP 地址
- 标识网络中的设备。
- 常见的 IP 地址格式:
- IPv4:如
192.168.1.1
- IPv6:如
2001:0db8:85a3:0000:0000:8a2e:0370:7334
- IPv4:如
1.2.2 端口号
- 用于标识设备上的具体应用程序。
- 范围:
0-65535
,其中:0-1023
是系统保留端口(如 HTTP 的端口 80)。1024-49151
是注册端口。49152-65535
是动态端口。
1.2.3 Socket 的工作流程
- 服务端:
- 创建 Socket。
- 绑定 IP 和端口。
- 监听客户端连接。
- 接受客户端连接。
- 处理数据通信。
- 客户端:
- 创建 Socket。
- 连接到服务端。
- 处理数据通信。
二、TCP 编程
TCP 是一种可靠的、面向连接的协议,适用于需要稳定数据传输的场景。
2.1 TCP 服务端
TCP 服务端的基本流程:
- 创建监听器,监听指定的 IP 和端口。
- 等待客户端连接。
- 接受连接并处理通信。
- 关闭连接。
示例代码
package mainimport ("bufio""fmt""net"
)func main() {// 1. 创建 TCP 监听器// net.Listen("tcp", "0.0.0.0:8888")// 1. tcp 表示使用网络协议是tcp// 2. 0.0.0.0:8888 表示在本地监听 8888端口,支持ipv4和ipv6listener, err := net.Listen("tcp", ":8080")if err != nil {fmt.Println("Error starting server:", err)return}defer listener.Close() // 延时关闭listenfmt.Println("TCP server is listening on port 8080...")// 循环等待客户端来链接for {// 2. 接受客户端连接conn, err := listener.Accept()if err != nil {fmt.Println("Error accepting connection:", err)continue}fmt.Println("Client connected:", conn.RemoteAddr())// 3. 使用一个协程处理客户端连接go handleConnection(conn)}
}func handleConnection(conn net.Conn) {// 延时关闭conndefer conn.Close()reader := bufio.NewReader(conn) // bufio.NewReader(conn) 将 conn(TCP 连接)包装成一个缓冲读取器for {// 读取客户端发送的数据message, err := reader.ReadString('\n') // 需要确保客户端发送的数据以换行符结尾,否则读取会一直阻塞if err != nil {fmt.Println("Connection closed by client:", conn.RemoteAddr())return}fmt.Printf("Received: %s", message)// 回复客户端conn.Write([]byte("Message received: " + message))}
}
2.2 TCP 客户端
TCP 客户端的基本流程:
- 连接到服务端。
- 发送数据。
- 接收服务端的响应。
- 关闭连接。
示例代码
package mainimport ("bufio""fmt""net""os"
)func main() {// 1. 连接到服务端conn, err := net.Dial("tcp", "localhost:8080")if err != nil {fmt.Println("Error connecting to server:", err)return}defer conn.Close()fmt.Println("Connected to server")// 2. 向服务端发送数据go func() {for {reader := bufio.NewReader(os.Stdin) // 从标准输入(os.Stdin)中读取用户输入的数据fmt.Print("Enter message: ")message, _ := reader.ReadString('\n') // ReadString(delim) 或 ReadBytes(delim) 读取数据,直到遇到指定的分隔符。conn.Write([]byte(message)) // 用于将数据写入连接(例如 TCP 连接、UDP 连接等)}}()// 3. 接收服务端的响应serverReader := bufio.NewReader(conn)for {response, err := serverReader.ReadString('\n')if err != nil {fmt.Println("Server closed connection")return}fmt.Printf("Server response: %s", response)}
}
三、UDP 编程
UDP 是一种无连接的协议,适合需要快速传输但不要求数据可靠性的场景。
3.1 UDP 服务端
UDP 服务端的基本流程:
- 创建一个 UDP 地址。
- 开启监听。
- 接收客户端发送的数据。
- 回复客户端。
示例代码
package mainimport ("fmt""net"
)func main() {// 创建 UDP 地址addr, err := net.ResolveUDPAddr("udp", ":8080")if err != nil {fmt.Println("Error resolving address:", err)return}// 创建 UDP 连接conn, err := net.ListenUDP("udp", addr)if err != nil {fmt.Println("Error starting UDP server:", err)return}defer conn.Close()fmt.Println("UDP server is listening on port 8080...")// 接收数据buffer := make([]byte, 1024)for {n, clientAddr, err := conn.ReadFromUDP(buffer)if err != nil {fmt.Println("Error reading from UDP:", err)continue}fmt.Printf("Received from %s: %s\n", clientAddr, string(buffer[:n]))// 回复客户端_, err = conn.WriteToUDP([]byte("Message received"), clientAddr)if err != nil {fmt.Println("Error writing to UDP:", err)}}
}
3.2 UDP 客户端
UDP 客户端的基本流程:
- 创建 UDP 地址。
- 发送数据到服务端。
- 接收服务端的响应。
示例代码
package mainimport ("fmt""net"
)func main() {// 创建 UDP 地址serverAddr, err := net.ResolveUDPAddr("udp", "localhost:8080")if err != nil {fmt.Println("Error resolving address:", err)return}// 创建 UDP 连接conn, err := net.DialUDP("udp", nil, serverAddr)if err != nil {fmt.Println("Error connecting to server:", err)return}defer conn.Close()// 发送数据message := "Hello, UDP server!"_, err = conn.Write([]byte(message))if err != nil {fmt.Println("Error sending data:", err)return}fmt.Println("Message sent:", message)// 接收数据buffer := make([]byte, 1024)n, _, err := conn.ReadFromUDP(buffer)if err != nil {fmt.Println("Error reading from server:", err)return}fmt.Printf("Server response: %s\n", string(buffer[:n]))
}
四、HTTP 编程
HTTP 是基于 TCP 的应用层协议,Go 的 net/http
包提供了强大的 HTTP 服务支持。
4.1 HTTP 服务端
示例代码
package mainimport ("fmt""net/http"
)func helloHandler(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Hello, World!")
}func main() {// 注册路由http.HandleFunc("/", helloHandler)// 启动服务fmt.Println("HTTP server is running on http://localhost:8080")http.ListenAndServe(":8080", nil)
}
4.2 HTTP 客户端
示例代码
package mainimport ("fmt""io/ioutil""net/http"
)func main() {// 发起 GET 请求resp, err := http.Get("http://localhost:8080")if err != nil {fmt.Println("Error making GET request:", err)return}defer resp.Body.Close()// 读取响应body, _ := ioutil.ReadAll(resp.Body)fmt.Println("Response from server:", string(body))
}
五、总结
- TCP 适合需要可靠传输的场景。
- UDP 适合需要快速传输的场景。
- HTTP 是基于 TCP 的高级协议,适用于 Web 开发。