小白都能看懂的TCP协议

1.定义:传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 定义。

2.tcp头部
小白都能看懂的TCP协议_第1张图片

  • 源/目的端口号:表示数据是从哪个进程来, 到哪个进程去;告知主机该报文段是来自哪里(源端口Source Port)以及传给哪个上层协议或应用程序(目的端口Destination Port)。
  • 32位序号:用来标识从TCP源端向TCP目标端发送的数据字节流,它表示在这个报文段中的第一个数据字节;在 SYN 报文中,序列号用于交换彼此的初识序列号,在其他报文中,序列号用于保证包的顺序。如果发送方发送的是四个报文段的序列号分别是: 1、2、3、4,但是到达接受方的顺序是 2、4、3、1,接受方可以通过序列号的大小顺序组装出原始的数据。
  • 32位确认号:只有ACK标志为1时,确认号字段才有效。它包含目标端所期望收到源端的下一个数据字节(ACK = seq + 1).
  • 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节); 没有任何选项字段的TCP头部长度为20字节;TCP头部最大长度是15 * 4 = 60。
  • 6位标志位:

①URG: 紧急指针是否有效,当 URG=1 时表明紧急指针字段有效,它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。
②ACK: 确认号是否有效,只有当 ACK=1 时确认号字段才有效。
③PSH: 接收方应该尽快将这个报文段交给应用层,而不再等到整个缓存都填满了后再向上交付。
④RST: 当 RST=1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
⑤SYN: 同步,SYN=1 表示这是一个连接请求或连接接受报文。
⑥FIN: 用来释放一个连接,FIN=1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。

  • 16位窗口大小:可以看出用于表示窗口大小的 Window SIze 只有 16 bit,也就是说窗口最大的大小是 65535 byte(64 KB)。为了让窗口再大一些,TCP协议引入了 “TCP 窗口缩放”选项作为窗口缩放的调控因子。调控因子的范围:0-14。
  • 16位校验和:对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证。在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部。
  • 16位紧急指针:指出在本报文段中紧急数据共有多少个字节(紧急数据放在本报文段数据的最前面)。
  • 40字节头部选项:可能包括"窗口扩大因子"、"时间戳"等选项。

3.确认应答机制
小白都能看懂的TCP协议_第2张图片
小白都能看懂的TCP协议_第3张图片
每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发.

4.超时重传机制
小白都能看懂的TCP协议_第4张图片

  • 主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B;
  • 如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发;

小白都能看懂的TCP协议_第5张图片
此时也可能是ACK丢弃了,因此主机B会收到很多重复数据. 那么TCP协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉。这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果。

  • 超时的时间如何确定?
    TCP为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间.
    • Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍.
    • 如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传.
    • 如果仍然得不到应答, 等待 4*500ms 进行重传. 依次类推, 以指数形式递增.
    • 累计到一定的重传次数, TCP认为网络或者对端主机出现异常, 强制关闭连接.

3.连接管理机制
大家应该都很清楚了,在正常情况下, TCP要经过三次握手建立连接, 四次挥手断开连接,我在这里不详细说了,下一篇博客我会详细介绍。

4.滑动窗口
网络环境就像复杂的交通链路。就好比一个沙漏,中间可能有一个地方流量非常的小,这个最小的口径决定了网络传输的真正速度。我们要考虑到带宽缓冲区等因素,如果一下子发送所有的数据只会加大网络压力,造成丢包重试,轻则传输更慢,重则网络崩溃。因为TCP是顺序发送的,操作系统将这些数据包一批一批的发送给对方,就像一个窗口,不停地往后移动。窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。
在TCP中,窗口的大小是在TCP三次握手后协定的,并且窗口的大小并不是固定的,而是会随着网络的情况进行调整
小白都能看懂的TCP协议_第6张图片

数据包分为四种:①已经发送并且确认的数据;②在窗口中,已经发送但尚未收到确认;③允许发送但尚未发送;④不可发送,只有当窗口滑动到此才允许发送。

  • 如果出现丢包,如何处理??

  • 数据包抵达,ACK丢弃。这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认,上面讲到过。

  • 数据包就直接丢了。假如此时我们发送1-1000,1001-2000,2001-3000,3001-4000四个数据包,此时1001-2000这个数据包丢了,发送端会一直收到 1001 这样的ACK,;如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数据 1001 - 2000 重新发送;这种机制被称为 “高速重发控制”(也叫 “快重传”)。

5.流量控制
接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包, 继而引起丢包重传等等一系列连锁反应。因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度,这个机制就叫做流量控制(Flow Control)。

  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段, 通过ACK端通知发送端。

  • 窗口大小字段越大, 说明网络的吞吐量越高。

  • 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端。

  • 发送端接受到这个窗口之后, 就会减慢自己的发送速度。

  • 如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端

  • 接收端如何把窗口大小告诉发送端呢? 回忆我们的TCP首部中, 有一个16位窗口字段, 就是存放了窗口大小信息;
    下面是wireshark的截图:
    在这里插入图片描述

  • 那么问题来了, 16位数字最大表示65535, 那么TCP窗口最大就是65535字节么?
    实际上, TCP首部40字节选项中还包含了一个窗口扩大因子M, 实际窗口大小是窗口字段的值左移 M 位。

6.拥塞控制
虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据.。但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题.因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。 在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的。TCP引入慢启动机制,先发少量的数据,探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据。

  • 主要有四种算法:慢开始、拥塞避免、快重传、快恢复。

  • 慢开始和拥塞避免:基于窗口的拥塞控制,在发送方维护一个拥塞窗口(cwnd),大小等于发送窗口,通过出现了超时来判断网络出现拥塞。慢开始的思路是一开始发送方发送一个字节,在收到接收方的确认,然后发送的字节数量增大一倍(也就是按照指数增长的速率),从小到大逐步增大cwnd,直到cwnd 达到慢开始门限(ssthresh),停止慢开始算法,使用拥塞避免算法,拥塞避免算法思路是增长速率变为线性增长,也就是每经过一个往返时间RTT就把发送方的cwnd加1,所以综上:
    当cwnd < ssthresh ,使用慢开始算法;
    当cwnd = ssthresh,可以使用慢开始算法,也可以使用拥塞算法;
    当cwnd > ssthresh,使用拥塞算法。
    小白都能看懂的TCP协议_第7张图片

  • 快重传和快恢复:如果收到3-ACK(发送方一连接收到3个对同一个报文段的重复确认),这种可能的情况是,并不是发生了拥塞,可能是报文丢失,所以发送方不执行慢开始算法,直接使用快重传算法,立即发送缺失的报文段。同时执行快恢复算法,将门限值(ssthresh)调整为此时cwnd的一半,并执行拥塞避免算法。

7.延迟应答
如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小.

  • 假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;

  • 但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;

  • 在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;

  • 如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M;

  • 那么所有的包都可以延迟应答么? 肯定也不是;

  • 数量限制: 每隔N个包就应答一次;

  • 时间限制: 超过最大延迟时间就应答一次;

  • 具体的数量和超时时间, 依操作系统不同也有差异; 一般N取2, 超时时间取200ms;

7.捎带应答

  • 在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 “一发一收” 的. 意味着客户端给服务器说了 “How are you”, 服务器也会给客户端回一个 “Fine, thank you”;
  • 那么这个时候ACK就可以搭顺风车, 和服务器回应的 “Fine, thank you” 一起回给客户端。
    小白都能看懂的TCP协议_第8张图片

你可能感兴趣的:(网络)