必知必会的TCP

一、概述

1、TCP的特点

  • 面向连接: 使用TCP传输数据必须先建立连接,传输完成之后再释放链接
  • 面向字节流:数据以流的形式进行传输
  • 全双工通信:建立TCP连接后,通信双方都能发送数据
  • 可靠:通过TCP连接传送的数据不丢失、无差错、不重复、按顺序到达

2、tcp的可靠性如何保证

  • 分块传送:数据被分割成最合适的数据块(UDP的数据报长度不变)
  • 等待确认:通过定时器等待接收端发送确认请求,收不到确认则重发
  • 确认回复:收到确认后发送确认回复(不是立即发送,通常推迟几分之一秒)
  • 数据校验:保持首部和数据的校验和,检测数据传输过程有无变化
  • 乱序排序:接收端能重排序数据,以正确的顺序交给应用端
  • 重复丢弃:接收端能丢弃重复的数据包
  • 流量缓冲:两端有固定大小的缓冲区(滑动窗口),防止速度不匹配丢数据

3、报文段格式

  • TCP虽面向字节流,但传送的数据单元 = 报文段
  • 报文段 = 首部 + 数据 2部分
  • TCP的全部功能体现在它首部中各字段的作用,故下面主要讲解TCP报文段的首部
  1. 首部前20个字符固定、后面有4n个字节是根据需而增加的选项
  2. 故 TCP首部最小长度 = 20字节

3.1、宏观位置

  • TCP数据被封装在IP数据报中

3.2、首部格式

  1. 第1-2两个字节:源端口号
  2. 第3-4两个字节:目的端口号

源端口号+ip首部中的源ip地址+目的端口号+ip首部中的目的ip地址,唯一的确定了一个tcp连接。

  1. 第5-8四个字节:32位序号。tcp提供全双工服务,两端都有各自的序号。解决网络包乱序的问题
  2. 第9-12四个字节:32位确认序列号。上次成功收到数据字节序号加1,ack为1才有效。解决丢包的问题

这两个字段是TCP可靠传输服务的关键部分,序列号是该报文段首字节的字节流编号(TCP把数据看成是有序的字节流,TCP隐式地对数据流的每个字节进行编号)。这样理解可能更直观,当报文被分解成多个报文段时,序列号就是报文段首字节在整个报文的偏移量。确定号指定下一个期待的字节。

  1. 第13个字节:数据偏移/首部长度

4位头部长度(header length):由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任何任选字段则长度为20字节,4位首部长度字段所能表示的最大值为1111,转化为10进制为15,15*4 = 60,故报头最大长度为60字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。

  1. 后面6bite:保留(6位):为将来定义新的用途保留,现在一般置0。
  2. 随后6bite:控制位:URG、 ACK、PSH 、 RST 、 SYN、 FIN
  3. 第15-16两个字节:窗口大小。接收端期望接收的字节数。解决流量控制的问题

是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度,从而达到流量控制。窗口大小为一个16bit字段,因而窗口大小最大为65535。

  1. 第17-18两个字节:校验和。由发送端计算和存储,由接收端校验。解决数据正确性问题

16位校验和(TCP check sum):由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏。注意,这个校验不仅包括TCP头部,也包括数据部分。这也是TCP可靠传输的一个重要保障。

  1. 第19-20两个字节:紧急指针

只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。

3.3、标识位说明

  1. URG:紧急指针标志,为1时表示紧急指针有效,该报文应该优先传送,为0则忽略紧急指针。
  2. ACK:确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。我们称携带ACK标识的TCP报文段为确认报文段。
  3. PSH:push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应优先将这个报文段交给应用程序,而不是在缓冲区排队。
  4. RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。我们称携带RST标志的TCP报文段为复位报文段。
  5. SYN:表示请求建立一个连接。在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。我们称携带SYN标志的TCP报文段为同步报文段。
  6. FIN:finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。我们称携带FIN标志的TCP报文段为结束报文段。

二、连接的建立与释放

1、TCP建立连接

  • TCP建立连接需三次握手
  • 具体介绍如下:

  • 第一次握手

客户端向服务器发送一个连接请求的报文段。

同步标志位设为1:SYN=1;

随机选择一个起始序号:seq=x;

不携带数据(因SYN位被设置为1的报文段不能携带数据,但是要消耗一个序号);

客户端进入同步已发送状态(SYN_SEND);

等待客户端的确认。

  • 第二次握手

服务器收到请求连接报文段后,若同意连接,则向客户端发回连接确认的报文段。(为该TCP连接分配TCP缓存,变量)

同步标志位设为1:SYN=1;

确认标志位设为1:ACK=1;

随机选择一个起始序号:seq=y;

确认号字段设为:ack=x+1;

不携带数据(因SYN位被设置为1的报文段不能携带数据,但是要消耗一个序号);

服务端进入同步已接受状态(SYN_RCVD)

  • 第三次握手

客户端收到确认报文段后,向服务端再次发送连接确认报文段。(为该TCP连接分配TCP缓存,变量)

确认标志位设为1:ACK=1;

序号:seq=x+1;

确认号字段:ack=y+1;

可携带数据(因SYN位未被设置为1,若不携带数据不消耗序号)

客户端、服务器都进入已创建状态

1.1、为什么要三次握手

三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。

第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常

第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常

第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常

所以三次握手就能确认双发收发功能都正常,缺一不可。

1.2、第 2 次握手传回了 ACK,为什么还要传回 SYN?

接收端传回发送端所发送的 ACK 是为了告诉客户端,我接收到的信息确实就是你所发送的信号了,这表明从客户端到服务端的通信是正常的。而回传 SYN 则是为了建立并确认从服务端到客户端的通信

2、连接释放过程

  • 第一次挥手

客户端向服务器发送一个连接释放的报文段。

终止控制位设为1:FIN=1;

报文段序号,设为前面已经传送过来的数据的最后一个字节的序号加1:seq=u;

可携带数据,(FIN报文段即使不携带数据,也要消耗一个序号)

客户端进入FIN-WAIT-1(终止等待1)状态。

  • 第二次挥手

服务器收到客户端的连接释放报文段后,则向客户端发回连接释放确认的报文段。

确认标志位设为1:ACK=1;

报文段序号,设为前面已经传送过来的数据的最后一个字节的序号加1:seq=u;

确认号字段设为:ack=u+1;

服务端就进入了CLOSE-WAIT(关闭等待)状态;

客户端->服务端已断开,服务端->客户端还未断开

  • 第三次挥手

若服务器已没有要向客户端发送的数据,则发出释放连接的报文段。

终止控制位设为1:FIN=1;

确认标志位设为1:ACK=1;

报文段序号:seq=w;

重复上次已发送的确认号字段 设为:ack=u+1;

可携带数据,(FIN报文段即使不携带数据,也要消耗一个序号)

服务端进入最后确认状态(LAST-ACK)

  • 第四次挥手

客户端收到释放连接的报文段后,则向服务器发回连接释放确认的报文段。

确认标志位设为1:ACK=1;

报文段序号:seq=u+1;

确认号字段设为:ack=w+1;

可携带数据,(FIN报文段即使不携带数据,也要消耗一个序号)

客户端就进入了TIME-WAIT(时间等待)状态,服务器进入CLOSED状态;

注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

3.1、为什么客户端最后还要等待2MSL?

MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。

第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

3.2、为什么建立连接是三次握手,关闭连接确是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。

而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

三、TCP 协议如何保证可靠传输

  • 应用数据被分割成 TCP 认为最适合发送的数据块。
  • TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
  • 校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
  • TCP 的接收端会丢弃重复的数据。
  • 流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)
  • 拥塞控制: 当网络拥塞时,减少数据的发送。
  • ARQ 协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
  • 超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段

1、ARQ 协议

自动重传请求(Automatic Repeat-reQuest,ARQ)是 OSI 模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧,它通常会重新发送。ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。

停止等待 ARQ 协议

停止等待协议是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认(回复 ACK)。如果过了一段时间(超时时间后),还是没有收到 ACK 确认,说明没有发送成功,需要重新发送,直到收到确认后再发下一个分组。

在停止等待协议中,若接收方收到重复分组,就丢弃该分组,但同时还要发送确认。

优缺点:

  • 优点: 简单
  • 缺点: 信道利用率低,等待时间长

连续 ARQ 协议

连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。

优缺点:

  • 优点: 信道利用率高,容易实现,即使确认丢失,也不必重传。
  • 缺点: 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5 条 消息,中间第三条丢失(3 号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N(回退 N),表示需要退回来重传已经发送过的 N 个消息。

2、滑动窗口和流量控制

滑动窗口包含发送窗口接收窗口:

发送窗口:任意时刻,发送方维护的一组连续的、允许发送帧的帧序号;

接收窗口:任意时刻,接收方维护的一组连续的、允许接收帧的帧序号;

滑动窗口工作原理 对于发送端:

  1. 每收到一个确认帧,发送窗口就向前滑动一个帧的距离
  2. 当发送窗口内无可发送的帧时(即窗口内的帧全部是已发送但未收到确认的帧),发送方就会停止发送,直到收到接收方发送的确认帧使窗口移动,窗口内有可以发送的帧,之后才开始继续发送

对于接收端:当收到数据帧后,将窗口向前移动一个位置,并发回确认帧,若收到的数据帧落在接收窗口之外,则一律丢弃。

TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据

3、拥塞控制

在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。

TCP 的拥塞控制采用了四种算法,即 慢开始拥塞避免快重传快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理 AQM),以减少网络拥塞的发生。

  • 慢开始: 慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞,因为现在还不知道网络的符合情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口数值。cwnd 初始值为 1,每经过一个传播轮次,cwnd 加倍。
  • 拥塞避免: 拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 RTT 就把发送放的 cwnd 加 1.
  • 快重传与快恢复: 在 TCP/IP 中,快速重传和恢复(fast retransmit and recovery,FRR)是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认件指出的数据段丢失了,并立即重传这些丢失的数据段。有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。

四、TCP, UDP 协议的区别

  • UDP 在传送数据之前不需要先建立连接,远地主机在收到 UDP 报文后,不需要给出任何确认。虽然 UDP 不提供可靠交付,但在某些情况下 UDP 却是一种最有效的工作方式(一般用于即时通信),比如: QQ 语音、 QQ 视频 、直播等等

  • TCP 提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。 TCP 不提供广播或多播服务。由于 TCP 要提供可靠的,面向连接的传输服务(TCP 的可靠体现在 TCP 在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源),这难以避免增加了许多开销,如确认,流量控制,计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多处理机资源。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章