当前位置:首页 > Go > 正文

Go语言实现TCP半关闭详解(网络编程入门教程)

Go语言网络编程中,理解TCP连接的生命周期非常重要。其中,TCP半关闭是一个常被忽视但非常实用的概念。本教程将带你从零开始,深入浅出地掌握TCP半关闭的原理与实现。

什么是TCP半关闭?

通常,当我们调用conn.Close()时,会同时关闭读写两端,即“全关闭”。而TCP半关闭指的是只关闭连接的一端(读或写),另一端仍然可以继续通信。

例如:客户端发送完所有数据后,可以关闭自己的写端(表示“我不再发了”),但仍然可以接收服务器的响应。这就是半关闭的典型应用场景。

Go语言实现TCP半关闭详解(网络编程入门教程) Go语言 TCP半关闭 网络编程 教程 第1张

Go语言如何实现TCP半关闭?

Go标准库中的net.Conn接口本身不直接提供半关闭方法。但我们可以通过类型断言将其转换为*net.TCPConn,然后调用其CloseWrite()CloseRead()方法。

关键方法说明:

  • CloseWrite():关闭写端,之后不能再发送数据,但可以继续读取。
  • CloseRead():关闭读端,之后不能再接收数据,但可以继续发送。

实战:Go语言TCP半关闭示例

下面是一个完整的客户端-服务器示例,演示如何使用CloseWrite()实现半关闭。

服务器端代码(server.go):

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"))}

客户端代码(client.go):

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连接的灵活控制!