TCP

三次握手

  • 客户端 -> 服务端:SYN = 1,seq = x
  • 服务端 -> 客户端:SYN = 1,ACK = 1,seq = y, ack = x + 1
  • 客户端 -> 服务端:ACK = 1, seq = x + 1, ack = y + 1

三次握手原因

假如说是两次握手的情况如下

  • 客户端第一次发送给服务端的报文因网络问题延迟了。此时客户端认为该报文已经失效。
  • 但是某时刻,报文到达服务端,服务端误认为是客户端发送的新请求,于时向客户端发送确认报文,同意建立连接。
  • 客户端以为没建立连接,不会发送请求。服务端以为建立了请求,等待客户端发送请求。造成资源浪费。

四次挥手

  • 客户端 -> 服务端:FIN = 1,seq = x
  • 服务端 -> 客户端:ACK = 1,ack = x + 1
    此时只是单方面表示客户端不会再发送数据,但是服务端还是可以继续发送数据
  • 服务端 -> 客户端:FIN = 1,seq = y
  • 客户端 -> 服务端:ACK = 1,ack = y + 1
    此时表示服务端不会再向客户端发送数据,此时四次挥手结束

重传机制

  • 超时重传
  • 快速重传(面试时候不要主动说)

超时重传

数据包丢失的情况下会触发,(RTT 代表一次来回的时间,RTO 代表重传超时的时间),对于 RTO 的设定应该略大于报文往返的时间。

快速重传

当接收到三个相同的 ack 报文时候,会触发快速重传。

滑动窗口

滑动窗口出现的原因是因为如果没有滑动窗口方案,那么就会是每发送一个数据,都要进行一次确认应答。当上一个收到应答之后,再发送下一个,效率会很低。滑动窗口的出现则是实现了只要在窗口大小内,无需等待确认应答,可以继续发送数据。中途如果某个保文缺失,也没有关系,因为可以通过下一个确认应答来确认,是一种累计应答的方案。

对于一条要发送的数据,包含四个部分

  • 已发送并收到 ACK 确认的数据(不在窗口之内)
  • 已发送但未收到 ACK 确认的数据(在窗口内)
  • 未发送但总大小在窗口大小内的数据(在窗口内)
  • 未发送但超过窗口大小的数据(在窗口之外)

每次成功接收 ACK 应答,窗口就会向后移动。

拥塞控制

出现网络拥堵的时候,如果持续发送大量数据包,可能会导致数据包延迟、丢失等,这时候 TCP 会触发超时重传,然后会继续造成网络负担家中,会越来越严重。拥塞控制就是为了避免这种情况,是通过调整滑动窗口的大小来实现的。

滑动窗口 size = min(接收窗口 size,拥塞窗口)最小值

拥塞窗口大小会根据一些方法来确定,比如:

慢启动

拥塞窗口每次接收一个 ACK 应答,就会加 1,因此是指数级增长的(窗口+1,会接收到 2 个 ACK,那么就会+1+1)