tcp 的三次握手与四次挥手
- 问1: 请你说一下tcp的三次握手
- 一次握手
- 两次握手
- 三次握手
- 问: 为什么不四(更多)次握手?
- 问 2: 请说一下 tcp 的 4 次挥手
- 一次挥手
- 两次挥手
- 问题:能不能等到数据传输完成再返回 ack?
- 三次挥手
- 四次挥手
- 问: 为什么要等两个最大报文存在时间?
bg: tcp 是可靠的连接,如何保证
- 建立连接: 三次握手
- 传输: 重传,拥塞机制
- 断开: 四次挥手
问1: 请你说一下tcp的三次握手
如果自己去设计一个tcp建立连接的流程会怎么做?
一次握手
客户端(请求连接:SYN)->服务端
问题 1: 客户端不知道服务端能不能收到
问题 2: 客户端不知道服务端是否可以发送数据
问题 3: (假设服务端收到请求,并同意连接)服务端不知道客户端是否可以接收到数据.
举个例子:
客户端连接的是一个关闭的服务器,如果只进行一次握手,客户端发送给关闭的服务器,服务器是不可能收到的.
结论: 一次握手不行
两次握手
客户端(请求连接:SYN)->服务端
服务端(ack+SYN)->客户端
问题 1: 服务端不知道客户端是否可以收到数据
举个例子:
第二次握手的数据丢包了,客户端没有收到
这时候客户端认为连接没有建立好(没有收到服务器的返回)
服务器认为连接已经建立好了
这时服务器发送数据给客户端,客户端是不接收的(因为客户端认为连接没有建立好)
结论: 两次握手也不行
三次握手
客户端(请求连接:SYN)->服务端
服务端(ack+SYN)->客户端
客户端(ack)->服务端
服务端知道客户端可以发送与接受数据
客户端知道服务端可以发送与接受数据
结论: 三次握手可以
问: 为什么不四(更多)次握手?
三次握手已经满足需求,多余的只是在浪费性能.
问 2: 请说一下 tcp 的 4 次挥手
自己来设计断开连接的流程会怎么设计?
终端 A 数据传输完成,准备与终端 B 断开连接
一次挥手
A(FIN)->B
问题 1:A不知道 B 是否能收到断开连接的信号
问题 2: A不知道 B 的数据是否已经传输完成,可能会丢失数据
举个例子:
B 并没有传输完成数据,这时 A 断开了连接,没有完成传输的数据就丢失了
结论: 一次挥手不行
两次挥手
A(FIN)->B
B(ack)->A
问题 1: A不知道 B 的数据是否已经传输完成,可能会丢失数据
问题:能不能等到数据传输完成再返回 ack?
不能
举个例子: 如果 A 发送 FIN 给 B ,这个过程可能丢包了,B 没有收到 A 发起的 FIN 就不会 ACK,所以 3 有重传,只要一段时间没有收到 ACK 就会重传 FIN
那么问题来了,如果等到数据传输完成再返回 ack,那么如果 B 数据没有传输完成,还需要传输很久,比如 10 分钟,那么这十分钟都没有返回 ack,A 端没收到 ack 会认为丢包了,就会不断的重发 FIN
结论: 两次挥手不行
三次挥手
A(FIN)->B
B(ack)->A
B(FIN)->A
问题: B 不知道 A 是否能收到发出的 FIN 信号,如果丢包,A 会保持 tcp 连接
四次挥手
A(FIN)->B
B(ack)->A
B(FIN)->A
A(ack)->B
保证双方数据都传输完毕,等待两个报文段最大存活时间就会断开
问: 为什么要等两个最大报文存在时间?
有两种说法:
- 确保 B 能收到 ack,不然 B 就会认为FIN丢包了,继续发送 FIN
- 最后 ack 后可能网络中还有一些数据包(丢包重传的),如果这时再建立连接可能会是同一个端口,那么这些(上一个连接)数据包可能在新的连接中被接受到,造成数据的错乱.