查看原文
其他

关于 TCP 需要了解的事儿

骑摩托马斯 精英程序员 2018-12-30

TCP 的特点

TCP 是面向连接的、可靠的流协议。 TCP 为提供可靠的传输,实行“顺序控制”或“重发控制”机制。此外还具备“流量控制”、“拥塞控制”、提供网络利用率等众多功能。

TCP在网络OSI的七层模型中的第四层——Transport层,IP在第三层——Network层,ARP在第二层——Data Link层,在第二层上的数据,我们叫Frame,在第三层上的数据叫Packet,第四层的数据叫Segment

数据首先会打到TCP的Segment中,然后TCP的Segment会打到IP的Packet中,然后再打到以太网Ethernet的Frame中,传到对端后,各个层解析自己的协议,然后把数据交给更高层的协议处理

TCP 可靠性传输

上图就是 TCP 建立通信示意图,包含了著名的三次握手和四次挥手。

在 TCP 中,通过序列号 (SYN) 与确认应答 (ACK) 提供可靠性,当发送端的数据到达接收主机时,接收端主机会返回一个已收到消息的通知,这个消息叫做确认应答 (ACK)

为什么建链接要3次握手,断链接需要4次挥手

  • 对于建链接的3次握手,主要是要初始化Sequence Number 的初始值。通信的双方要互相通知对方自己的初始化的Sequence Number(缩写为ISN:Inital Sequence Number)——所以叫SYN,全称Synchronize Sequence Numbers。也就上图中的 x 和 y。这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上的传输的问题而乱序(TCP会用这个序号来拼接数据)

  • 对于4次挥手,其实你仔细看是2次,因为TCP是全双工的,所以,发送方和接收方都需要Fin和Ack。只不过,有一方是被动的,所以看上去就成了所谓的4次挥手。

上图演示的是一种理想状态下的 TCP 连接过程,但是现实中的连接过程可能并没有那么顺利,可能会出现丢包的情况。这就需要 TCP 的重发机制来保证数据的可靠性传输。

丢包包括两种情况,一种是数据在到达接收端的过程中就发生了丢失,另外一种是接收端接受到了数据,但是确认应答在返回的途中发挥了丢失。

上述这些确认应答处理、重发控制以及重复控制等功能都可以通过序列号实现。序列号是安顺序给发送数据的每一个字节(8 位字节)都标上号码的编号。接收端查询接收数据 TCP 首部中的序列号和数据的长度,将自己下一步应该接收的序号作为确认应答反送回去。接这样通过序列号和确认应答号,TCP 可以实现可靠传输

利用窗口控制提高速度

TCP 以 1 个段为单位,即 MSS(Maximum Segment Size) 最大消息长度,进行数据传输。MSS 是在三次握手的时候,在两端主机之间被计算出来的,三次握手的时候会在 TCP 的首部中写入 MSS 选项,告诉对方自己的接口能够适用的 MSS 大小。然后在两者之间选择一个较小的值投入使用。

TCP 在数据传输中,每发一个段进行一次确认应答的处理。这样的传输方式有一个缺点。那就是,包的往返时间越长通信性能就越低。

为了解决这个问题,TCP 引入了窗口的概念。确认应答不再是以每个分段,而是以更大的单位进行确认,也就是说,发送段主机,在发送了一个段以后不必要一直等待确认应答,而是继续发送。

窗口大小就是指无需等待确认应答而可以继续发送数据的最大值。这个机制实现了通过使用大量的缓冲区,来对多个段同时进行确认应答的功能。

窗口控制与重发控制

确认应答未能返回情况

在这种情况下,数据已经到达对端,是不需要再进行重发的。然而,在没有使用窗口控制的时候,没有收到确认应答的数据都会被重发。而使用了窗口控制,某些确认应答即便丢失也无需重发。

如上图所示,即使 3001 和 4001 的确认应答在返回途中丢失了,但是客户端收到了 5001 的确认应答,则客户端会继续发送下面的数据而不会进行重发。

报文段丢失

如上图所示,当发生某个报文段丢失后,发送段会一直收到序列号为 1001 的确认应答,因此在窗口比较大,又出现报文段丢失的情况下,同一个序号的确认应答将会被重复不断的返回。而发送段主机如果连续 3 次收到同一个确认应答,就会将其所对应的数据进行重发。这种机制币之前提到的超时管理更加高效,因此也被称作高速重发控制

流控制

TCP 提供一种机制可以让发送端根据接收端的实际接收能力控制发送的数据流。这就是所谓的流控制。它的具体操作是接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端会发送不超过这个限度的数据。该大小限度就是上面提到的窗口的大小。

TCP 首部中,专门有一个字段来通知窗口大小。接收主机将自己可以接收的缓冲区大小放入这个字段中通知给发送端。这个字段越大,说明网络吞吐量越高。

如图所示,当接收端收到从 3001 号开始的数据断后其缓冲区即满,不得不暂时停止接收数据。之后,在收到发送窗口更新通知后通信才得以继续进行。

拥塞控制

为了防止在通信刚开始时发送大量数据,引起网络拥堵的情况,TCP 在通信一开始时就会通过一个叫慢启动的算法算出数值,对发送数据进行控制。

首先,为了在发送端调节所需发送数据的量,定义了一个叫“拥塞窗口”的概念。在慢启动的时候,将这个拥塞窗口的大小设置为 1 个数据段 (1 MSS),之后每收到一次确认应答,拥塞窗口的值就加 1。在发送数据包时,将拥塞窗口的大小与接收端主机通知的窗口大小做比较,然后按照它们当中较小的值,发送比其还要小的数据量。

TCP头格式

我们来看一下TCP头的格式

需要注意这么几点:

  • TCP的包是没有IP地址的,那是IP层上的事。但是有源端口和目标端口。

  • 一个TCP连接需要四个元组来表示是同一个连接(src_ip, src_port, dst_ip, dst_port)准确说是五元组,还有一个是协议。但因为这里只是说TCP协议,所以,这里我只说四元组。

  • Sequence Number是包的序号,用来解决网络包乱序(reordering)问题。

  • Acknowledgement Number就是ACK——用于确认收到,用来解决不丢包的问题。

  • Window又叫Advertised-Window,也就是著名的滑动窗口(Sliding Window),用于解决流控的。

  • TCP Flag ,也就是包的类型,主要是用于操控TCP的状态机的。

原文出处:https://juejin.im/post/5b8ccda1e51d4538c77ab254


- MORE | 更多精彩文章 -

精英程序员的技术世界

即刻点击阅读原文,发现技术世界的美好

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存