记录 - 4.29
什么是TCP?
面向连接的、可靠的、字节流的。
UDP和TCP 的不同 : 连接、服务对象、可靠性、拥塞/流量控制、首部开销(UDP 没有【选项】字段)、传输方式(TCP 是流式传输,没有边界,保证顺序和可靠;TCP是一个个包发送,有边界)、分片不同
为什么 UDP 头部没有「首部长度」字段,而 TCP 头部有「首部长度」字段呢?
TCP 有可变长的「选项」字段,而 UDP 头部长度则是不会变化的,无需多一个字段去记录 UDP 的首部长度。
TCP 连接建立过程:
客户端会随机初始化序号,将此序号放在TCP 首部的【序号】中,同时SYN为1,发送给服务端,之后客户端处于SYN-SENT状态
服务端收到SYN报文后,将自己的随机初始化序号填到TCP首部的【序号】这种,并把 收到的SYN报文中的序号+1填入当前报文的【确认应答号】中,并把ACK和SYN标志置为1,之后服务端处于SYN-RCVD
客户端收到服务端报文后,回应ACK。【确认应答号】填入服务端序号+1,发送给服务端后,客户端进入ESTABLISHED状态。并且此次发送可以携带数据。
为什么是三次握手?
三次握手才能保证双方具有接收和发送的能力。
三次握手才可以阻止重复历史连接的初始化(主要原因)
在两次握手的情况下,服务端没有中间状态给客户端来阻止历史连接,导致服务端可能建立一个历史连接,造成资源浪费。
当收到旧连接时,当服务端进入SYN_RCVD后向服务端发送ACK,服务端根据ACK发送RST中止连接,如果只有两次连接,那在服务端收到历史连接的SYN 报文后就直接进入ESTABLISHED 状态,并直接就进行数据的发送,但这些数据都是不会被客户端接收的,当ACK 到达后,客户端仍然会回复RST中止连接。
三次握手才可以同步双方的初始序列号
三次握手才可以避免资源浪费
小结:
TCP 建立连接时,通过三次握手能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号。序列号能够保证数据包不重复、不丢弃和按序传输。
不使用「两次握手」和「四次握手」的原因:
「两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
「四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。
为什么每次建立 TCP 连接时,初始化的序列号要求不一样?
为了防止历史报文被下一个相同四元组的连接接收(主要方面);
为了安全性,防止黑客伪造的相同序列号的 TCP 报文被对方接收;
初始化序列号是基于时钟计时器递增的,基本不可能会随机成一样的初始化序列号。
既然IP层会分片,为什么TCP层还需要MSS 呢?
如果一个IP分片丢失,整个IP 报文的所有分片都得重传。
为达到最佳的传输效能会进行MSS值的协商,这样也就不需要IP层的分片了。
一个TCP分片丢失后,重发也是以MSS为单位的,不用重传所有的分片。
第一次握手丢失了,会发生什么?
重传SYN报文。通常,重传5次,第一次为1秒,每次超时的时间是上一次的两倍。
第二次握手丢失了,会发生什么?
丢失的两个内容:ACK和SYN。服务端和客户端都会触发重传
客户端会重传 SYN 报文,也就是第一次握手,最大重传次数由 tcp_syn_retries内核参数决定;
服务端会重传 SYN-ACK 报文,也就是第二次握手,最大重传次数由 tcp_synack_retries 内核参数决定。
时间两倍,超过次数则断开连接。
第三次握手丢失了,会发生什么?
ACK报文是不会有重传的。当第三次握手的丢失时,服务端会重传SYN-ACK报文,直到收到第三次握手或者达到最大重传次数。