这张图展示了在 Muduo 网络库中,TCP 连接关闭时的一个序列图。这个过程展示了客户端和服务端在发送完数据后的连接关闭步骤,具体涉及到几个类和方法的调用。下面是详细解释:
Client 发起关闭:
- 客户端调用
TcpConnection
对象的shutdown()
方法。 - 该方法接着调用
shutdownInLoop()
,这是在事件循环中执行关闭操作。
- 客户端调用
TcpConnection 处理关闭:
shutdownInLoop()
方法进一步调用Socket
对象的shutdownWrite()
方法,表示写操作的关闭。
Socket 发送 FIN 分节:
shutdownWrite()
方法内部会调用系统的shutdown()
函数,发送一个 FIN 分节给对方(Peer),表示数据发送完毕,关闭写入操作。
Peer 接收 FIN 分节:
- 对方(Peer)接收到 FIN 分节后,会进行 ACK(确认)并发送自己的 FIN 分节(如果它也打算关闭连接),表示自己也关闭了写操作。
本地(Local)读取关闭事件:
- 在本地,
TcpConnection
会通过handleRead()
方法处理读取事件。当对方的 FIN 分节到达时,读取操作返回 0 字节,这表明对方已经关闭连接。
- 在本地,
TcpConnection 处理关闭:
- 读取到 0 字节后,
TcpConnection
的handleClose()
方法会被调用,处理关闭连接的逻辑。 handleClose()
方法会触发connectionCallback()
回调,通知上层应用连接已关闭。
- 读取到 0 字节后,
资源清理:
- 最终,
TcpConnection
对象会被析构(dtor & close),并关闭底层的套接字资源,完成连接的完全关闭。
- 最终,
细节补充:
Half-Close:
- 半关闭(Half-Close)指的是 TCP 连接的一端关闭其写操作,但仍然保持读操作开放。这样,对方仍然可以继续发送数据。
- 在图中,当
shutdownWrite()
发送 FIN 分节后,虽然本地关闭了写操作,但仍然可以从对方接收数据直到对方也关闭连接。
完整的关闭过程:
- 当
shutdownWrite()
发送 FIN 分节后,对方接收并返回 ACK,表示确认接收到 FIN 分节。 - 对方也可以选择在发送完剩余数据后再发送自己的 FIN 分节,最终由本地
TcpConnection
处理读取到 0 字节的事件并关闭连接。
- 当
通过这个序列图,我们可以清晰地看到 Muduo 库是如何通过一系列方法调用和事件处理来优雅地关闭 TCP 连接的。