参考:公众号 小林coding
常见回答:三次握手保证双方都具有接受和发送数据的能力。
主要原因:
1. 防止重复历史连接的初始化
2.同步双方初始序列号
3.避免资源的浪费
1. TCP为什么三次握手?
1.1 防止重复历史连接的初始化
序列号seq标记已发送数据的位置,确认号ack表示数据已接受,期望下一次数据序列号seq = ack
当因为网络拥塞导致超时重传建立连接的请求:设两次请求seq分别为:100, 200,在第二次请求发送后,客户端记录seq = 200, 即使网络恢复旧请求成功得到响应,此时ack = 101, 在客户端处校验不通过,发送RST终止这次连接。
如果采用两次握手:(中间绿色的服务端发送数据就被浪费,并且需要进行连接的销毁)
1.2 同步双方初始序列号
使用序列号可以保证数据的发送是有序的,同时记录已发送数据的位置,便于对比请求响应ack确定下一次发送数据的位置。
在三次握手的情况下,双方都对请求作出响应,表示数据接受,初始化发送数据的序列号;保证双方都进入数据可发送和接受的状态。
其中的四次握手,说的服务端响应阶段需要发送标志位:SYN, ACK,SYN用于初始化序列号,ACK表示确定数据接受成功;而最优的三次握手中,将这两个阶段放到一起,减少一次请求
3.其他问题
3.1 为什么客户端和服务端的初始化序列号不同?
可以注意到,在三次握手的建立过程中,很多情况下客户端的seq = x, 而服务端的序列号 seq = y
这样做的原因为了防止历史报文被下一个相同的四元组(tcp连接)接收
服务端和接收端中分别维护窗口大小,用于接收数据;如果使用不同的seq, 可以保证及时连接重置,旧的历史数据也很大程度不会落入接收窗口中,不会使数据污染。
假设每次初始化序列号都是0:
3.2 为什么要在传输层分片?
MTU:网络中最大数据包长度, 包括:IP头 + TCP头 + 数据报,以太网一般1500
MSS:最大数据报长度
当数据报超过MSS的时候进行数据分片。
如果在IP中进行分片,网络层中不包含重传机制,一旦某一个分片丢失,会导致这次请求的所有数据都要重传。
3.3 SYN攻击
在TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的 SYN
报文,服务端每接收到一个 SYN
报文,就进入SYN_RCVD
状态,但服务端发送出去的 ACK + SYN
报文,无法得到未知 IP 主机的 ACK
应答,久而久之就会占满服务端的半连接队列,使得服务器不能为正常用户服务。
4、四次挥手
进入连接断开阶段:
第一次:客户端数据发送结束,发送FIN, 服务端接受后进入close_wait状态
第二次:服务端响应客户端断开连接的请求
第三次:服务端接收数据结束,发送FIN, 客户端接收后进入time_wait状态
第四次: 客户端响应服务端请求,发送ack, 在time_wait阶段下等待2MSL时间;如果这个时间间隔内没有收到服务端的请求,进入close状态
主动关闭连接的,才有time_wait状态
相比于三次握手,这里的FIN 和 ACK需要分开,表示服务端仍可以接受数据;因此需要四次挥手
4.1 为什么需要2MSL
什么是MSL: 是报文段在网络中传输的最长时间;超过这个时间,就会被丢弃
2MSL:客户端发送确认报文ACK + 等待服务端请求(如果ACK丢失,重新发送FIN)两次请求的最长存活时间;当超过这个时间,表示报文发送成功。
4.2 为什么要有TIME_WAIT状态
1. 防止历史数据被后面相同的四元组(TCP连接)接收。假设第一次TCP连接中seq = 100, 整个过程中发送一次seq = 101的报文,但是因为网络产生延迟,在TCP关闭前也没有成功接收。再重新建立一个TCP连接使用seq = 100, 此时上一次连接中的报文到达,并且接收窗口 [100, x]可以接受这次的数据;导致了新的连接接受了上一次的旧数据。
2. 保证接收数据方能够正常断开;如果没有2MSL, 当客户端发送ACK后直接进入关闭状态,如果ACK丢包,导致服务端重新发送FIN, 此时没有接收方,服务端一直没有断开连接文章来源:https://www.toymoban.com/news/detail-426773.html
后续LInux中的看不懂。。。慢慢看吧,哎文章来源地址https://www.toymoban.com/news/detail-426773.html
到了这里,关于TCP为什么三次握手?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!