TCPTransmission Control Protocol传输控制协议是互联网协议栈中传输层的核心协议之一它提供面向连接的、可靠的、基于字节流的通信。要理解TCP的工作原理最重要的两个过程就是三次握手建立连接和四次挥手释放连接。本文将结合经典的报文交换图深入解析这两个过程并解答常见疑问如为什么是三次为什么是四次TIME_WAIT有什么用。一、TCP基础概念回顾在深入握手挥手之前先了解几个关键字段序列号seq占4字节表示本报文段所发送数据的第一个字节的序号。在建立连接时双方会随机初始化一个序号ISN。确认号ack占4字节仅在ACK标志位为1时有效表示期望收到对方下一个报文段数据的第一个字节的序号通常为上次收到对方数据的最后一个序号加1。标志位SYN同步序号用于建立连接。ACK确认表示确认号字段有效。FIN结束用于释放连接。其他标志RST、PSH、URG本文不展开。二、三次握手建立可靠的连接三次握手的主要目的是确保双方都具备收发能力并同步初始序列号。过程如下图所示结合经典状态转移text客户端 服务器 |-------- SYN1, seqx ----------| (1) SYN-SENT |------ SYN1, ACK1, seqy, ackx1 ----| (2) SYN-RCVD |-------- ACK1, seqx1, acky1 -------| (3) 进入ESTABLISHED第一步客户端发送SYN报文客户端主动打开连接发送一个SYN标志位置1的报文段其中包含一个随机初始化的序列号seq x。此时客户端进入SYN-SENT状态。第二步服务器回复SYNACK服务器收到SYN后如果同意建立连接则回复一个SYN和ACK标志位均为1的报文段确认号ack x 1表示期望收到客户端下一个字节序号为x1的数据同时确认了客户端的SYN。服务器也随机初始化自己的序列号seq y。此时服务器进入SYN-RCVD状态。第三步客户端发送ACK确认客户端收到服务器的SYNACK后需要发送一个ACK报文段确认号ack y 1表示收到服务器的SYN。序列号seq x 1因为之前发送的SYN不携带数据所以序列号1。此时客户端进入ESTABLISHED状态。服务器收到这个ACK后也进入ESTABLISHED状态连接建立完成。为什么必须是三次握手防止已失效的连接请求突然到达服务器如果客户端发出的第一个SYN因为网络延迟在连接释放后才到达服务器服务器误以为新请求并回复SYNACK。如果只有两次握手服务器就会建立连接并等待数据浪费资源。而三次握手时客户端不会对服务器的SYNACK再发送确认服务器收不到最后的ACK就不会建立连接。确保双方收发能力正常第一次握手证明客户端的发送能力和服务器的接收能力第二次握手证明服务器的发送能力和客户端的接收能力第三次握手确认双方都已就绪。同步初始序列号双方需要交换初始序列号以便后续数据的有序传输。三、四次挥手优雅地释放连接TCP是全双工协议即两个方向的数据传输可以独立关闭。因此释放连接时需要分别关闭每个方向过程通常需要四次交互。假设客户端主动关闭连接text主动方客户端 被动方服务器 |-------- FIN1, sequ --------| (1) FIN-WAIT-1 |------ ACK1, seqv, acku1 -----| (2) CLOSE-WAIT (此时进入FIN-WAIT-2) |------ FIN1, ACK1, seqw, acku1 ----| (3) LAST-ACK |-------- ACK1, sequ1, ackw1 ------| (4) TIME-WAIT (2MSL后关闭)第一步主动方发送FIN主动方如客户端发送一个FIN标志位置1的报文段序列号为seq u等于之前发送数据的最后一个字节的序号1。此时主动方进入FIN-WAIT-1状态表示自己不再发送数据。第二步被动方回复ACK被动方收到FIN后发送一个ACK报文段确认号ack u 1。序列号seq v等于自己发送数据的最后一个字节序号1。被动方进入CLOSE-WAIT状态。主动方收到ACK后进入FIN-WAIT-2状态等待被动方关闭连接。此时被动方可能还有数据要发送所以主动方仍需接收数据。第三步被动方发送FIN被动方处理完剩余数据后也发送一个FIN报文段可携带ACK标志FIN1, ACK1。序列号seq w可能基于之前的v但通常wv因为数据可能已经发送完毕。确认号仍为ack u1。被动方进入LAST-ACK状态等待最后的ACK。第四步主动方回复ACK主动方收到FIN后发送一个ACK报文段确认号ack w1。序列号seq u1。此时主动方进入TIME-WAIT状态等待2MSL最大报文段生存时间后进入CLOSED状态。被动方收到ACK后立即进入CLOSED状态。为什么必须是四次挥手全双工关闭的独立性当主动方发送FIN时仅表示自己不再发送数据但被动方可能还有数据未发送完所以不能立即关闭。被动方先发送ACK表示收到关闭请求待数据发送完毕后再发送自己的FIN。因此ACK和FIN通常分开发送形成四次。特殊情况如果被动方在收到FIN后已经没有数据要发送可以将ACK和FIN合并在一个报文段中发送从而变成三次挥手即第二、三步合并。但标准实现仍建议分开发送以确保兼容性和可靠性。为什么需要TIME-WAIT状态TIME-WAIT状态持续2MSLMSL为报文段最大生存时间通常为30秒、1分钟或2分钟主要作用确保最后的ACK能被对方收到如果最后的ACK丢失被动方会超时重发FIN主动方在TIME-WAIT状态下可以重发ACK保证连接可靠关闭。防止旧报文干扰新连接等待足够时间让所有属于旧连接的报文段在网络中消失避免它们被后续使用相同端口的新连接错误接收。四、常见问题与深入探讨1. 三次握手可以携带数据吗第一次和第二次握手不能携带数据因为此时连接尚未建立携带数据会被对端丢弃或导致安全隐患。第三次握手可以携带数据因为此时客户端已确认服务器有接收能力且服务器一旦收到数据就会交给应用层。2. 为什么初始序列号ISN要随机为了防止历史报文段被误认为是新连接的报文。如果ISN固定攻击者可能伪造RST重置连接。随机化ISN如RFC 1948中建议的算法可提高安全性。3. SYN Flood攻击是什么如何防范攻击者伪造大量源IP发送SYN报文但不完成第三次握手导致服务器维护大量半连接SYN-RCVD状态耗尽资源。防范方法SYN Cookie服务器不直接保存半连接信息而是将连接参数加密后作为初始序列号Cookie在SYNACK中返回。收到ACK后验证Cookie合法才分配资源。增加半连接队列大小、缩短超时时间等。4. TIME-WAIT为什么是2MSLMSL是报文段在网络中的最大生存时间。主动方发送ACK后这个ACK可能丢失被动方会重传FIN。主动方需要等待足够时间至少1MSL接收重传的FIN并再发送ACK又需要1MSL。因此2MSL能保证最后一个ACK到达对端如果丢失对端重传的FIN到达主动方主动方重置2MSL计时器并重发ACK。本连接的所有报文段从网络中消失。5. 如果连接双方同时打开或同时关闭TCP设计允许同时打开双方同时发送SYN和同时关闭双方同时发送FIN。同时打开需要四次握手但通过特殊处理可以建立连接同时关闭需要四次挥手但会进入类似FIN-WAIT的状态。实际应用中很少见但TCP规范支持。五、总结TCP的三次握手和四次挥手是网络通信的基石。理解它们不仅有助于面试和考试更能帮助我们在网络编程中排查问题如连接建立缓慢、大量TIME-WAIT、半连接耗尽等。本文结合经典的状态迁移和报文交换从原理到常见问题做了详细解析。希望读者能通过抓包工具如Wireshark亲自观察这些过程加深理解。最后如果你对网络协议感兴趣推荐阅读《TCP/IP详解 卷1》和RFC 793那里有更全面的描述。
TCP三次握手与四次挥手
TCPTransmission Control Protocol传输控制协议是互联网协议栈中传输层的核心协议之一它提供面向连接的、可靠的、基于字节流的通信。要理解TCP的工作原理最重要的两个过程就是三次握手建立连接和四次挥手释放连接。本文将结合经典的报文交换图深入解析这两个过程并解答常见疑问如为什么是三次为什么是四次TIME_WAIT有什么用。一、TCP基础概念回顾在深入握手挥手之前先了解几个关键字段序列号seq占4字节表示本报文段所发送数据的第一个字节的序号。在建立连接时双方会随机初始化一个序号ISN。确认号ack占4字节仅在ACK标志位为1时有效表示期望收到对方下一个报文段数据的第一个字节的序号通常为上次收到对方数据的最后一个序号加1。标志位SYN同步序号用于建立连接。ACK确认表示确认号字段有效。FIN结束用于释放连接。其他标志RST、PSH、URG本文不展开。二、三次握手建立可靠的连接三次握手的主要目的是确保双方都具备收发能力并同步初始序列号。过程如下图所示结合经典状态转移text客户端 服务器 |-------- SYN1, seqx ----------| (1) SYN-SENT |------ SYN1, ACK1, seqy, ackx1 ----| (2) SYN-RCVD |-------- ACK1, seqx1, acky1 -------| (3) 进入ESTABLISHED第一步客户端发送SYN报文客户端主动打开连接发送一个SYN标志位置1的报文段其中包含一个随机初始化的序列号seq x。此时客户端进入SYN-SENT状态。第二步服务器回复SYNACK服务器收到SYN后如果同意建立连接则回复一个SYN和ACK标志位均为1的报文段确认号ack x 1表示期望收到客户端下一个字节序号为x1的数据同时确认了客户端的SYN。服务器也随机初始化自己的序列号seq y。此时服务器进入SYN-RCVD状态。第三步客户端发送ACK确认客户端收到服务器的SYNACK后需要发送一个ACK报文段确认号ack y 1表示收到服务器的SYN。序列号seq x 1因为之前发送的SYN不携带数据所以序列号1。此时客户端进入ESTABLISHED状态。服务器收到这个ACK后也进入ESTABLISHED状态连接建立完成。为什么必须是三次握手防止已失效的连接请求突然到达服务器如果客户端发出的第一个SYN因为网络延迟在连接释放后才到达服务器服务器误以为新请求并回复SYNACK。如果只有两次握手服务器就会建立连接并等待数据浪费资源。而三次握手时客户端不会对服务器的SYNACK再发送确认服务器收不到最后的ACK就不会建立连接。确保双方收发能力正常第一次握手证明客户端的发送能力和服务器的接收能力第二次握手证明服务器的发送能力和客户端的接收能力第三次握手确认双方都已就绪。同步初始序列号双方需要交换初始序列号以便后续数据的有序传输。三、四次挥手优雅地释放连接TCP是全双工协议即两个方向的数据传输可以独立关闭。因此释放连接时需要分别关闭每个方向过程通常需要四次交互。假设客户端主动关闭连接text主动方客户端 被动方服务器 |-------- FIN1, sequ --------| (1) FIN-WAIT-1 |------ ACK1, seqv, acku1 -----| (2) CLOSE-WAIT (此时进入FIN-WAIT-2) |------ FIN1, ACK1, seqw, acku1 ----| (3) LAST-ACK |-------- ACK1, sequ1, ackw1 ------| (4) TIME-WAIT (2MSL后关闭)第一步主动方发送FIN主动方如客户端发送一个FIN标志位置1的报文段序列号为seq u等于之前发送数据的最后一个字节的序号1。此时主动方进入FIN-WAIT-1状态表示自己不再发送数据。第二步被动方回复ACK被动方收到FIN后发送一个ACK报文段确认号ack u 1。序列号seq v等于自己发送数据的最后一个字节序号1。被动方进入CLOSE-WAIT状态。主动方收到ACK后进入FIN-WAIT-2状态等待被动方关闭连接。此时被动方可能还有数据要发送所以主动方仍需接收数据。第三步被动方发送FIN被动方处理完剩余数据后也发送一个FIN报文段可携带ACK标志FIN1, ACK1。序列号seq w可能基于之前的v但通常wv因为数据可能已经发送完毕。确认号仍为ack u1。被动方进入LAST-ACK状态等待最后的ACK。第四步主动方回复ACK主动方收到FIN后发送一个ACK报文段确认号ack w1。序列号seq u1。此时主动方进入TIME-WAIT状态等待2MSL最大报文段生存时间后进入CLOSED状态。被动方收到ACK后立即进入CLOSED状态。为什么必须是四次挥手全双工关闭的独立性当主动方发送FIN时仅表示自己不再发送数据但被动方可能还有数据未发送完所以不能立即关闭。被动方先发送ACK表示收到关闭请求待数据发送完毕后再发送自己的FIN。因此ACK和FIN通常分开发送形成四次。特殊情况如果被动方在收到FIN后已经没有数据要发送可以将ACK和FIN合并在一个报文段中发送从而变成三次挥手即第二、三步合并。但标准实现仍建议分开发送以确保兼容性和可靠性。为什么需要TIME-WAIT状态TIME-WAIT状态持续2MSLMSL为报文段最大生存时间通常为30秒、1分钟或2分钟主要作用确保最后的ACK能被对方收到如果最后的ACK丢失被动方会超时重发FIN主动方在TIME-WAIT状态下可以重发ACK保证连接可靠关闭。防止旧报文干扰新连接等待足够时间让所有属于旧连接的报文段在网络中消失避免它们被后续使用相同端口的新连接错误接收。四、常见问题与深入探讨1. 三次握手可以携带数据吗第一次和第二次握手不能携带数据因为此时连接尚未建立携带数据会被对端丢弃或导致安全隐患。第三次握手可以携带数据因为此时客户端已确认服务器有接收能力且服务器一旦收到数据就会交给应用层。2. 为什么初始序列号ISN要随机为了防止历史报文段被误认为是新连接的报文。如果ISN固定攻击者可能伪造RST重置连接。随机化ISN如RFC 1948中建议的算法可提高安全性。3. SYN Flood攻击是什么如何防范攻击者伪造大量源IP发送SYN报文但不完成第三次握手导致服务器维护大量半连接SYN-RCVD状态耗尽资源。防范方法SYN Cookie服务器不直接保存半连接信息而是将连接参数加密后作为初始序列号Cookie在SYNACK中返回。收到ACK后验证Cookie合法才分配资源。增加半连接队列大小、缩短超时时间等。4. TIME-WAIT为什么是2MSLMSL是报文段在网络中的最大生存时间。主动方发送ACK后这个ACK可能丢失被动方会重传FIN。主动方需要等待足够时间至少1MSL接收重传的FIN并再发送ACK又需要1MSL。因此2MSL能保证最后一个ACK到达对端如果丢失对端重传的FIN到达主动方主动方重置2MSL计时器并重发ACK。本连接的所有报文段从网络中消失。5. 如果连接双方同时打开或同时关闭TCP设计允许同时打开双方同时发送SYN和同时关闭双方同时发送FIN。同时打开需要四次握手但通过特殊处理可以建立连接同时关闭需要四次挥手但会进入类似FIN-WAIT的状态。实际应用中很少见但TCP规范支持。五、总结TCP的三次握手和四次挥手是网络通信的基石。理解它们不仅有助于面试和考试更能帮助我们在网络编程中排查问题如连接建立缓慢、大量TIME-WAIT、半连接耗尽等。本文结合经典的状态迁移和报文交换从原理到常见问题做了详细解析。希望读者能通过抓包工具如Wireshark亲自观察这些过程加深理解。最后如果你对网络协议感兴趣推荐阅读《TCP/IP详解 卷1》和RFC 793那里有更全面的描述。