Woowen You can do anything you set your mind to, man

TCP

TCP结构

TCP的头部如果不计可选字段,通常20个字节 序号随着时间不断增长,每隔0.5秒就增加64000,一直增长到2^32,然后在从0开始递增,一个序号的周期为4.55小时

TCP 三次握手

  • 客户端发起TCP连接请求,建立连接时发送 SYN标志变1 + ISN(初始序号)
  • 服务端返回包含服务端的初始序号的SYN报文,同时将确认序号设置为客户端的ISN+1,做为对客户端SYN报文的确认
  • 客户端收到服务端的SYN和ack,将ack+1做为确认序号发送返还给服务端

TCP为什么采用3次握手

TCP的核心是为了建立高可靠性高性能的传输连接 3次握手是两军问题的折中方案,3次也是理论上建立高可靠的最小理论值,也可以使用4次握手甚至5次握手,但是后面的意义不大,为了提高性能3次就够了

fast open

大概原理是,TCP不用等待3次握手完成就可以开始传输数据

  • 发起方第一次申请建立连接时(确认双方都支持TFO-TCP fast open),包尾加一个FOC请求, 接收方收到FOC请求后会根据发起方的IP生成一个cookie,随着SYN和ack一起返回发起方
  • 发起方收到cookie之后保存起来
  • 当之前的连接断开了.需要重新建立TCP连接时,发起方直接将cookie随着SYN以及需要发送的数据一起发给接收方
  • 接收方验证cookie之后就可以不用等待第三次的ack返回直接发送数据
  • fast open默认关闭状态

TCP 四次挥手

建立连接需要三次握手,而关闭连接需要四次挥手,因为TCP是全双工,一端可以发送/接收数据,因此都需要关闭,所以需要四次

TIME_WAIT

TIME_WAIT状态也成为2MSL状态,每个TCP的实现必须选择一个MSL,它是每个报文在网络中传输的最长时间,也是报文被丢弃前在网络中存留的最长时间

当一端的TCP执行主动关闭并发送最后一个ACK之后必须在TIME_WAIT状态等待2MSL时间,防止这个ACK丢失而超时重发,在2MSL等待期间,(客户端的IP地址和端口号,服务端的IP地址和端口号)不能被使用

TCP流量控制

TCP客户端拥有发送窗口,服务端拥有接收窗口,服务端的接收窗口大小受限制于系统,应用和硬件控制,发送端的窗口受限制于接收方的窗口大小控制,也就是发送方的窗口不能超过接收方的窗口,避免发送的流量超过接收方的处理能力

TCP建立连接之前会经历三次握手,第一次发送方发送SYN + 初始序号表示需要建立连接,然后接收放返回SYN(接收方初始序号) + 确认序号(发送方初始序号+1)来确认建立,接收方返回的SYN + ack其中包含了两个重要的数据

  • 1.期望收到的下一个序号,接收方返回的ack中是发送方的序号+1,表示之前的数据都已经接收
  • 2.窗口大小,窗口大小的数据在报文的window字段中显示,默认(2^16 - 1 = 65535)字节大小,可以通过可选字段中的配置进行扩容到31位
  • 3.假设发送端已经发送了A个字节的数据,接收方返回已经接收B个字节+ack中的窗口大小C,那么发送方就可以计算出接收方还能接受多少数据,通过C - (A - B)

  • 图中,在原滑动窗口中,32之前的数据都表示接收端已经接收并确认,32~51表示窗口的大小也就是能够接收的数据大小
  • 每当发送方发送数据并收到ack确认时窗口左侧就会右移相应的字节

因此窗口中的数据可以分为4类

  • 1.发送且已经确认
  • 2.发生但还没有确认
  • 3.没有发送,但没有超过窗口大小,表示能发送的剩余数据大小
  • 4.不能发送,超过窗口限制

因此发送方只有收到确认报文才会移动窗口,当前面有数据没有确认,哪怕后续数据已经收到,接收端还是需要继续发送之前的确认报文,表示之前数据还没有收到,例如发送方发送1,2,3,4,接收方接收1,2,4其中3网络中超过MSL或者其他原因没有收到,接收方还是不会发送ack4,一直会发送ack3,一直到发送方超时或者接收方连续3次返回ack3,就会触发重传,发送方就会重传3的报文

慢启动

TCP刚启动的时候,发送端只知道接收端能接受的数据大小,并不知道网络的状况,还有接收端的确认情况,比如虽然接收端能一共接收10个字节,但是我一次发送9个字节,而每个报文都会有一个定时器,当超过定时器时,接收端只是确认到第8个字节,因此还不会发送ack9,这时发送端以为丢了继续重发这时就会进入死循环,因此使用慢启动让大家互相有个熟悉的过程

  • 慢启动一开始窗口发送一个报文长度(MSS)大小,当收到接收端的一个确认时,就会发送2MSS大小
  • 当继续收到2个ack确认时就会指数增长,继续发送4个,8个,一直到触发拥塞避免设定的限制值
  • 当超过限制值时开始以线性增长,比如设置的限制值为15,当发送方一次发送16个时发现超过了,那么后续就会16+1 ,发送17个,18个,19个以此类推
  • 当发送到20个的时候,其中有丢包存在,那么就会直接减半,变成10个继续发送(拥塞避免设置的限制值为10,窗口为10+3),继续发送13,14,这就是拥塞避免

快速重传

当发送端发送之后,接收端其中某个包丢失了,那么这时发送端会一直等待接收端的确认报文,这时发送方就会一直等待一直到超时然后重传,快速重传就是为了解决超时的问题,毕竟超时过程是漫长的

快速重传的原理就是当收到连续3个相同的ack时就触发重传如上图收到了4个ack2,会立刻重新传2,3,4,5

选择重传

上面重传效率高,但是其实3,4,5都已经收到了,继续重传不是浪费带宽和时间么.因此多了一种机制叫选择重传,选择重传的机制是我告诉你哪些丢了,哪些已经收到了,你只需要传丢失的那个就好了.

在TCP可选字段中有个叫sack的东西,用来标志哪些已经被接收方收到的,这有发送方只需要重传丢失的报文就可以了 ack~sack为丢失报文,需要重传

快速恢复

早起的TCP算法为Tahoe,基本意思就是当慢启动,然后指数增加,达到拥塞避免阈值时线性增加,发生丢包情况(超时或者3个重复ack)就直接将窗口改成1,然后再次启用慢启动,这样减低了网络的利用率

当出现超时或者3个重复ack时将拥塞避免阈值设为窗口大小的一半,然后窗口设置为一半加3继续进入拥塞避免算法中线性增加,因为不是将窗口设置为1直接打入慢启动,而是直接进入拥塞避免,因此称为快速恢复

参考

https://www.zhihu.com/question/32255109

http://coolshell.cn/articles/11564.html

Woowen 浙ICP备15013647号