什么是TCP

tcp是面向连接的可靠的基于字节流的传输协议

  • 面向连接:一定是一对一的才能连接,不能像udp一样可以一个主机同时向多个主机发送消息
  • 可靠的:无论网络链路中出现什么链路变化,TCP都可以保证一个报文一定能到达接收端
  • 字节流:消息是「没有边界」的,所以无论我们消息有多大都可以进行传输。并且消息是「有序的」,当「前一个」消息没有收到的时候,即使它先收到了后面的字节已经收到,那么也不能扔给应用层去处理,同时对「重复」的报文会自动丢弃。

TCP头部信息

image.png

三次握手

image.png

  1. 客户端会随机一个初始化序号(client_isn),将此序号置于TCP首部的【序列号】字段中,同时把SYN标志位置为1,标识SYN报文
  2. 服务端收到客户端报文后,服务端也随机生成一个序号(server_isn),将此序号置于TCP首部的【序列号】字段中,接着把【确认应答号】字段填入client_isn +1,把SYN和ACK标志为1
  3. 客户端收到服务端的报文后,将新报文中的ACK标志为1,将【确认应答号】字段填入server_isn+1,这次报文是可以携带数据的

Q:为什么第三次握手可以携带数据
A:因为第三次握手服务端接受到后双方都变为ESTABLISHED状态,此时连接就建立完毕了

Q:为什么是三次握手,不是两次、或者四次
A:

  • 避免历史连接,防止旧的重复连接初始化造成混乱。(主要原因)

image.png
如果是两次握手就不能判断当前连接是否是历史连接,三次握手则可以再发送第三次报文时,根据上下文判断是否是重复连接,然后选择发送RST报文终止连接还是ACK确认连接

  • 三次握手才可以同步双方的初始序列号

image.png
四次握手其实也能够可靠的同步双方的初始化序号,由于第二步和第三步可以优化成一步,所以就成三次握手

  • 三次握手才可以避免资源浪费

image.png
客户端超时重发,会造成资源浪费

四次挥手

image.png

  • 客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入FIN_WAIT_1 状态。
  • 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。
  • 客户端收到服务端的 ACK 应答报文后,之后进入FIN_WAIT_2 状态。
  • 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。
  • 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
  • 服务器收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。
  • 客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此客户端也完成连接的关闭。

Q:为什么是四次挥手
A:

  • 客户端向服务端发送FIN报文时,只是代表不发送消息了,但是还可以接收消息
  • 服务端在接收到FIN报文时,发送ACK确认消息,但可能还有数据没有处理完,所以要等服务端不再发送消息了,才能发送FIN报文

所以服务端的FIN报文和ACK报文要分开发送,比三次握手多了一次,所以是四次挥手

Q:为什么TIME_WAIT时间是2MSL
A:

  • TCP报文时基于IP协议的,IP头中有一个TTL字段,是IP数据包可以经过的最大路由,每经过一个路由就递减1,当减到0的时候数据将别丢弃,同时发送ICMP报文给源主机
  • MSL是报文最大生存时间,超过这个时间报文将被丢弃,所以MSL应该大于等于TTL消耗为0的时间,以确保报文被自然消亡

TIME_WAIT是2MSL的原因是:

  • 服务端发送FIN报文给客户端,客户端接受到FIN报文后开始发送ACK报文给服务端,假如服务端没有接受到 ACK报文就会超过一个MSL超时重发FIN报文
  • 客户端再发送一个ACK报文,如果一个MSL没有收到再重发的FIN报文,就算断开连接成功,这么一来一回正好2MSL

确认重传机制

image.png
A和B确认连接后,每次A发送消息都会带上SeqNo,并且B在接收后,返回给Ack消息,AckNo=(SeqNo+报文字节数),如果A一个超时时间没有收到ACK消息,则会重传

滑动窗口

image.png

  • 普通的一个请求一个ack太慢,可以一次发送多条数据,窗口大小决定了可以发送多少数据,上图窗口为4000,这个窗口值是根据接收方的缓存区大小决定的
  • 当主机A收到5001的应答,但未收到3001、4001的应答时,我们可以考虑两种情况,但是都不影响,因为可以确定5001之前的数据都被接收到了
    • 3001、4001的应答较慢,5001的应答较快,所以先到达;
    • 3001、4001的应答丢失了;
  • 如果出现丢包怎么处理,有两种情况
    • 数据到了,Ack丢失,可以通过后续的Ack来确认
    • 数据包直接丢了,接受端会一直发送1001的ack,当发送超过3次,就会触发重传

流量控制

image.png
接受端处理速度是有限的,TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制

延迟应答

如果接收到数据没有充满窗口,就会延迟应答,这样就可以充分利用窗口大小
但是也不是所有的包都延迟应答,会受到数量限制和时间限制,数量就是没隔N个包就应答一次,没隔多长时间就应答一次,一般N为2,时间为200ms

搬运来着:https://mp.weixin.qq.com/s/tH8RFmjrveOmgLvk9hmrkw