在Go语言的网络编程中,理解TCP连接的生命周期非常重要。其中,TCP半关闭是一个常被忽视但非常实用的概念。本教程将带你从零开始,深入浅出地掌握TCP半关闭的原理与实现。
通常,当我们调用conn.Close()时,会同时关闭读写两端,即“全关闭”。而TCP半关闭指的是只关闭连接的一端(读或写),另一端仍然可以继续通信。
例如:客户端发送完所有数据后,可以关闭自己的写端(表示“我不再发了”),但仍然可以接收服务器的响应。这就是半关闭的典型应用场景。
Go标准库中的net.Conn接口本身不直接提供半关闭方法。但我们可以通过类型断言将其转换为*net.TCPConn,然后调用其CloseWrite()或CloseRead()方法。
CloseWrite():关闭写端,之后不能再发送数据,但可以继续读取。CloseRead():关闭读端,之后不能再接收数据,但可以继续发送。下面是一个完整的客户端-服务器示例,演示如何使用CloseWrite()实现半关闭。
package mainimport ( "bufio" "fmt" "net")func main() { listener, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } defer listener.Close() fmt.Println("服务器启动,监听 :8080") for { conn, err := listener.Accept() if err != nil { fmt.Println("接受连接失败:", err) continue } go handleConnection(conn) }}func handleConnection(conn net.Conn) { defer conn.Close() reader := bufio.NewReader(conn) // 读取客户端发送的数据 for { message, err := reader.ReadString('\n') if err != nil { // 客户端关闭写端后,会收到 EOF fmt.Println("客户端已关闭写端,停止读取") break } fmt.Print("收到消息: ", message) } // 回复客户端 conn.Write([]byte("服务器已收到所有数据!\n"))} package mainimport ( "fmt" "net")func main() { conn, err := net.Dial("tcp", "localhost:8080") if err != nil { panic(err) } defer conn.Close() // 发送几条消息 conn.Write([]byte("Hello from client\n")) conn.Write([]byte("This is the second message\n")) // 关键步骤:半关闭 —— 关闭写端 if tcpConn, ok := conn.(*net.TCPConn); ok { err = tcpConn.CloseWrite() if err != nil { fmt.Println("关闭写端失败:", err) return } fmt.Println("已关闭写端,不再发送数据") } // 仍然可以读取服务器的响应 buffer := make([]byte, 1024) n, err := conn.Read(buffer) if err == nil { fmt.Printf("收到服务器回复: %s", string(buffer[:n])) }} 1. 先运行服务器:go run server.go
2. 再运行客户端:go run client.go
你会看到服务器打印出两条消息,并提示“客户端已关闭写端”,然后客户端成功收到服务器的回复。这正是TCP半关闭的威力所在!
*net.TCPConn支持CloseWrite()和CloseRead(),UDP等其他协议不支持。CloseWrite()后,对端会收到EOF(即io.EOF错误),这是正常现象。conn.Close()来释放资源。通过本Go语言网络编程教程,你已经掌握了TCP半关闭的核心概念与实现方式。这项技术在构建高性能、可靠通信协议(如HTTP/1.1 的持久连接)时非常有用。希望这篇教程能帮助你更深入地理解TCP连接的灵活控制!
本文由主机测评网于2025-12-19发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025129887.html