断开连接 四次挥手
原因
TCP 四次挥手是为了满足 TCP 连接的全双工特性:两个方向都可以自由传输
保证数据传输的完整性:两方都完成了数据发送和接收并且都同意断开连接
可靠地终止连接以及避免数据混淆和错误等需求:每个方向都需要单独确认导致四次挥手过程
这些步骤确保了网络通信的可靠性和稳定性,是 TCP 协议的重要组成部分
流程
- 第一次挥手:
- 动作发起方:客户端。当客户端完成数据传输任务后,想要关闭连接,就会向服务器发送一个带有
FIN
(Finish)标志位的报文段,表示客户端不再发送数据。 - 客户端状态变化:发送完
FIN
报文后,客户端进入FIN_WAIT_1
(终止等待 1)状态,等待服务器的确认。
- 动作发起方:客户端。当客户端完成数据传输任务后,想要关闭连接,就会向服务器发送一个带有
- 第二次挥手:
- 动作发起方:服务器。服务器收到客户端的
FIN
报文后,知道客户端想要关闭连接,就会返回一个ACK
(Acknowledgment)确认报文段,表示已经收到了客户端的关闭请求。 - 服务器状态变化:此时服务器进入
CLOSE_WAIT
(关闭等待)状态。在这个状态下,服务器可能还会继续向客户端发送一些剩余的数据。而客户端收到服务器的ACK
报文后,进入FIN_WAIT_2
(终止等待 2)状态,继续等待服务器发送关闭连接的请求。
- 动作发起方:服务器。服务器收到客户端的
- 第三次挥手:
- 动作发起方:服务器。当服务器完成所有数据的发送后,就会向客户端发送一个带有
FIN
标志位的报文段,告知客户端自己也准备好关闭连接了。 - 服务器状态变化:发送完该报文后,服务器进入
LAST_ACK
(最后确认)状态,等待客户端的最后确认。
- 动作发起方:服务器。当服务器完成所有数据的发送后,就会向客户端发送一个带有
- 第四次挥手:
- 动作发起方:客户端。客户端收到服务器的
FIN
报文后,会向服务器发送一个ACK
确认报文段,表示已经收到了服务器的关闭请求。 - 客户端状态变化:发送完
ACK
报文后,客户端进入TIME_WAIT
(时间等待)状态。在这个状态下,客户端会等待一段时间(通常是 2 倍的报文最大生存时间2MSL
),以确保服务器能够收到最后一个ACK
报文。如果在TIME_WAIT
状态期间没有收到服务器的重传请求,客户端就会认为服务器已经成功收到了ACK
报文,然后关闭连接,进入CLOSED
状态。服务器收到客户端的ACK
报文后,也会关闭连接,进入CLOSED
状态。
- 动作发起方:客户端。客户端收到服务器的
注意
1 经过四次挥手就已经断开了
2 客户端和服务端都可以主动断开
3 每次收到一个有效的数据就立即回复ACK告诉对方接收成功防止超时重传
4 其他包可以和ack一起发送
问题
问题一: 被动方在FIN包之后,为什么没有立即回复FIN包,为什么要立即回复ACK包?
1 主动方发送完FIN之后 就不在发送数据了
2 可是被动方可能还需要发送数据
3 要立即ACK回复防止超时重传
4 不能发送FIN因为被对方可能还需要发送数据
5 FIN包在TCP协议中也被当成一种特殊报文需要ACK确认 确保信息传递准确和可靠性
问题二: 主动断开方在发送最后一次ACK包之后为什么要等待2msl以后再关闭?
1 2mls (两个数据包在网络中存在最大时间)
2 主动方发送的ack可能丢失 触发被动发超时重传 会再向主动方发送FIN
3 2mls时间再没有收到新的fin则说明被动方收到了最后指令主动方可以关闭了
滑动窗口
定义
滑动窗口是 TCP用于流量控制和拥塞控制的一种机制。它允许发送方在收到接收方的确认之前可以连续发送多个数据包,而接收方通过告知发送方自己的接收窗口大小来控制发送方的发送速度。
流程
发送方操作:
- 开始时,发送窗口大小由接收方告知。发送方在窗口内发送数据段,每发送一个数据段,窗口的下限不变,但上限会根据已发送但未确认的数据段数量动态变化。
- 当收到接收方的确认(ACK)后,发送窗口下限会根据确认号向前移动。
接收方操作:
- 接收方根据自己的缓冲区大小设定接收窗口大小。
- 接收方在处理数据的过程中,会不断地从缓冲区中取出数据进行处理,
- 当缓冲区有了更多空间后,又会增大接收窗口大小并告知发送方,
- 发送方可以再次增大发送窗口上限,发送更多的数据。
作用
流量控制:
- 防止接收方被发送方的数据 “淹没”
提高传输效率:
- 相比于停止 - 等待协议
- 发送方发送一个数据段后等待接收方确认,收到确认后再发送下一个数据段
- 滑动窗口允许发送方在收到确认之前发送多个数据段,
- 充分利用了网络带宽,提高了数据传输的效率。
应用
接收方缓冲区状态:
- 如前面所述,当接收方缓冲区快满时,会减小接收窗口大小;当缓冲区有更多空间时,会增大接收窗口大小
网络拥塞状况:
- 在拥塞控制机制下,如果网络出现拥塞(如路由器缓冲区溢出、链路带宽饱和等情况),发送方会减小发送窗口大小,减少注入网络的数据量,以缓解拥塞。
应用层需求和协议限制:
- 有些应用可能对数据传输的速度和顺序有特殊要求,这也会影响窗口大小的调整。
在数据接收时候 如果丢失了数据 接收端返回最小序列丢失号之前ACK
流量控制
原因
避免数据丢失:如果发送方发送的数据量超过了接收方缓冲区所能容纳,超出部分的数据将会丢失
确保接收方正常处理数据:接收方处理数据的速度是有限的。如果发送方发送数据的速度太快,接收方可能来不及处理,导致数据在缓冲区堆积。这不仅可能会引起数据丢失,还可能会使接收方系统出现性能问题。
方法
接收方传递信息给发送方 使其不要太快发送数据
是一种端对端的控制 主要方式就是返回ACK中会包含接收窗口大小
利用窗口大小控制发送方的数据发送多少
接收方发送ack返回窗口大小
利用窗口大小控制发送数据大小
粘包问题
粘包原因
TCP字节流传输
- TCP 是面向字节流的协议是一种没有边界的 可合并的传输数据方式 ,它不像 UDP(用户数据报协议)那样有消息边界。这意味着 TCP 会把应用层交付的数据仅仅看作是一连串的字节,而不关心这些字节具体代表几个完整的消息。例如,发送方连续发送了两个小消息,在接收方的底层缓冲区中,这两个消息可能会被当作一个连续的字节流接收,从而出现粘包现象。
Nagle 算法的影响
- Nagle 算法是为了减少网络中微小数据包(小包)的数量而设计的。它会将多个小的发送请求合并为一个较大的发送请求。例如,应用程序连续调用多次发送函数发送小数据块,Nagle 算法会将这些小数据块缓存起来,直到满足一定条件(如积累了足够的数据或者收到了之前发送数据的确认)才会发送。这样一来,在接收方就可能会收到合并后的大数据块,产生粘包问题。
解决方法
1 设置标志位
起始标志位
缺点:最后一个包 不知到哪个是结尾
场景:适用在发送的内容比较固定,或者已知的场景下
结束标志位
缺点:但是传输数据可能和标志相同 无法判断 错误拆包
场景:发送内容都是固定的没有用户输入内容 不可能和标志位重复
2 固定包大小
缺点: 弊端 当传输数据小于空间时候 会浪费空间
适用场景: 发送大文件 文件较大 就得分几次发送
3 先发送长度 在发送数据包
方法: 发送长度,发送数据
4 短连接
方法: 每次发送SOCKET时候 使用新的缓冲区 将数据放在不同缓冲区就不会粘包
每次发送之前申请新的socket
缺点: 每次发送之前都需要建立连接 浪费时间和空间 资源
使用场景: 用户发送数据操作间隔时间很长时候