计算机网络测试人关于TCP的学习和梳理

Posted 黑黑白白君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机网络测试人关于TCP的学习和梳理相关的知识,希望对你有一定的参考价值。

通过阅读《计算机网络–自顶向下方法》,以及结合最近面试的一些经历,作此笔记进行梳理和总结,也为日后的回顾作基底。

文章目录


1)什么是TCP?

1.1 TCP与运输层

运输层(Transport Layer)位于应用层和网络层之间,该层协议为运行在不同主机上的应用进程之间提供了逻辑通信功能。

  • 即应用进程使用运输层提供的逻辑通信功能彼此发送报文,而无须考虑承载这些报文的物理基础设施的细节。
  • 运输层和网络层的关系:运输层位于网络层之上,网络层提供主机之间的逻辑通信服务,运输层为运行在不同主机上的进程之间提供逻辑通信服务。
  • 关于网络层级架构具体介绍可移步《【计算机网络】OSI与TCP/IP网络架构》

运输层协议在端系统中实现:

  • 在发送端:将来自发送应用进程的应用报文分块,每块加上一个运输层首部以生成运输层报文段(segment),然后传递给网络层。
  • 在接收端:处理接收到的报文段,将其中的数据供接收应用进程使用。

*面试常问之TCP和HTTP的联系和区别

联系:

区别:

  • HTTP属于应用层协议,定义了传输数据内容的规范。

  • TCP属于运输层协议,定义了数据传输和连接方式的规范。

  • HTTP算是短连接,TCP算是长连接。

因特网有两种协议(TCP和UDP),可为调用的应用程序提供一组不同的传输层服务。

  • UDP(用户数据报协):为调用它的应用程序提供了一种不可靠的、无连接的服务。
  • TCP(传输控制协议):为调用它的应用程序提供了一种可靠的、面向连接的服务。

TCP和UDP最基本的责任是将两个端系统间IP的交付服务扩展成运行在端系统上的两个进程之间的交付服务,即运输层的多路复用和多路分解:

  • 多路分解:将运输层报文段中的数据交付到正确的套接字。
  • 多路复用:从不同套接字中收集数据块、为其封装首部信息以生成报文段、将报文段传递给网络层。
    • 要求:套接字有唯一标识符(源端口号字段)、报文段有特殊字段指示目的套接字(目的端口号字段)。
      • 端口号(0 - 65535)
      • 周知端口号(0 - 1023),在[RFC1700]给出,在[RFC3232]更新。

网络层协议(IP,网际协议)为主机之间提供逻辑通信,其服务模型是尽力而为交付服务(best-effort delivery
service)。

  • 因为其不确保报文段的交付,不保证报文段的按序交付,不保证报文段中的数据的完整性,因此也被称为不可靠服务(unreliable service)

1.2 TCP与UDP

  • 无连接运输:UDP

    • 工作原理:给从应用进程得到的数据添加源和目的端口号字段,以及两个其他的小字段(长度和校验和),然后交给网络层,反之则将IP报文段的数据根据目的端口号交付给正确的应用进程。
    • 适用场景
      • 实时应用(通常要求最小的发送速率,不过分延迟,可容忍部分数据丢失)
      • 特定服务(无连接因此可支持更多的活跃客户,以及更快)
      • 如DNS、SNMP、网络电话、实时视频会议、流式存储音频与视频

  • 面向连接的运输:TCP

    • 工作原理
      • 面向连接:通过三次握手建立连接,四次挥手断开连接。
      • 通过差错检测、重传、累积确认、定时器、序号和确认号来保证可靠传输。
      • TCP定义在RFC793、RFC1122、RFC1323、RFC2018、RFC2581中。
    • 常用场景:如SMTP、Telnet等。

  • UDP与TCP的区别:

    • 无连接与有连接
    • TCP要求系统资源较多,UDP较少
    • UDP程序结构较简单
    • TCP保证数据正确性,UDP可能丢包
    • TCP保证数据顺序,UDP不保证
    • 详细的区别可参考:https://blog.csdn.net/Li_Ning_/article/details/52117463


2)面试常问之TCP如何实现可靠传输?

TCP服务模型是一个字节流,TCP必须检测并修补所有在IP层(及下面的层)产生的数据传输问题,如丢包、重复以及错误。

2.1 连接管理

一个TCP连接通常分为3个阶段:启动、数据传输、退出(关闭)。

  • 一个TCP连接由一对端点或套接字构成,通信的每一端都由一对(IP地址、端口号)所唯一标识。
  • 连接建立过程(三次握手):

    三次握手的目的不仅在于让通信双方了解一个连接正在建立,而且还利用SYN报文段交换彼此的初始序列号(ISN)。
    1. 客户端发送一个SYN报文段,并指明自己想要连接的端口号和初始序列号x(表明传送数据时的第一个数据字节的序号是 x)。
    2. 服务器发送响应SYN报文段,包含其初始序列号y,此外确认号ack=x+1(若出现丢失的情况,该SYN段会被重传)。
    3. 客户端为了确认服务器的SYN,发送确认号ack=y+1的报文。

*面试常问之为什么是三次握手而不是两次?

为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。

  • 详细原因:如果在发送过程中的话,假如是两次:
    • 当A给B发送一个连接请求,因为网络的原因该请求没有按时到达,A就会重新发送一次请求,这次请求正常到,然后B就会给A一个确认请求,此时就可以传送数据了。
    • 但是当A第一次发送的数据又来到了(A以为这个包已经丢失了),那么B就会再次向A发送一个确认,此时的A就不知道这个确认的意义了,而B就会在一直等待着A给他发送信息(如果这样的次数很多就会导致资源浪费)。
    • 所以不能是两次。

  • 连接关闭过程(四次挥手):

    通过发送一个FIN报文段来发起关闭操作,由于TCP的通信模型是双向的,所以只有连接双方都完成关闭操作后,才构成一个完整关闭。
    1. 连接的主动关闭者发送一个FIN段,进入FIN_WAIT_1。
    2. 被动关闭者发送的报文段中确认号ack=u+1,以表明其已经成功收到主动关闭者的FIN。此时,上层应用程序会被告知连接的另一端已经提出了关闭的请求。
    3. 若此时没有要发送的数据时,应用程序会发起自己的关闭操作,接着被动关闭者的身份转变为主动关闭者,并发送自己的FIN。
    4. 收到连接释放报文段后,为了完成连接的关闭,还会发送一个ACK用于确认上一个FIN。注意,当出现FIN丢失的情况,发送方会重新传输直到收到一个ACK确认。

*面试常问之为什么是四次挥手而不是三次?

因为TCP连接是全双工的,也就是说接收到FIN只是说没有数据再发过来,但是还是可以向对方发送数据的,也就是说接受到一个FIN只是关闭了一个方向的数据传输,另一个方向还可以继续发送数据

  • 前两次挥手只是确认关闭了一个方向的数据,加上后面两次挥手才真正的关闭了整个全双工连接。

  • 当socket在ESTABISHED状态时,它想主动关闭连接于是向对方发送FIN请求,发送完FIN请求后它处于FIN_WAIT_1状态,当对方确认ACK报文后则处于FIN_WAIT_2状态。

    • FIN_WAIT_2表示半连接,也就是有一方要求关闭连接,另一方收到请求但是告诉它我还有一些数据要发送稍后会关闭。
    • TIME_WAIT状态表示收到对方的FIN并发送出ACK

如果是三次挥手,则可能在关闭后还有一个方向没有关

*面试常问之2MSL:

客户端接收到服务器端的 FIN 报文后进入TIME_WAIT状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:

  • 确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
  • 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文

2.2 校验和

发送的数据包的二进制相加然后取反,目的是检测数据在传输过程中的任何变化。

  • 如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。

2.3 序列号和ACK信号

发送方按照顺序给要发送的数据包的每个字节都标上编号。
接收方接收到发送方的数据包之后,回传一个ACK信号,标识下一个需求的数据包初始字节编号。

  • 序列号
    • TCP提供一个字节流接口,把一个应用程序的字节流转换为一组IP可以携带的分组,这些分组包含序列号。
    • 序列号在TCP中实际代表了每个分组的第一个字节在整个数据流中的字节偏移。
    • 通过序列号的使用,一个TCP接收端可丢弃重复的报文段和记录以乱序到达的报文段。

  • ACK信号
    • 当TCP接收到另一端的数据时,会发送一个确认。
    • TCP使用的ACK是累积的,一个指示字节号N的ACK表示了所有直到N的字节(但不包括N)已经成功被接收了。

2.4 超时重传

发送方没有接收到响应的ACK报文原因可能有两点:

  • 数据在传输过程中由于网络原因等直接全体丢包,接收方没有接收到。
  • 接收方接收到了响应的数据,但是发送的ACK报文响应却由于网络原因丢包了。

TCP在解决这个问题的时候引入了一个新的机制,叫做超时重传机制。

发送方在发送完数据后等待一个时间,该时间内没有接收到ACK报文,那么就会重新发送刚才的数据。

  • 如果是上述第一个原因,则接收方收到二次重发的数据后,便进行ACK应答。
  • 如果是第二个原因,接收方发现接收的数据已存在(判断存在的根据就是序列号,所以说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送ACK应答。
  • 等待时间的设定:
    • 为了保证在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。
      • 超时以500ms(0.5秒)为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。
      • 重发一次后,仍未响应,那么等待2500ms的时间后,再次重传。等待4500ms的时间继续重传。以一个指数的形式增长。
    • 累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。

2.5 滑动窗口

TCP必需要解决的可靠传输以及包乱序(reordering)的问题,所以,TCP必需要知道网络实际的数据处理带宽或是数据处理速度,这样才不会引起网络拥塞,导致丢包。

  • 发送方滑动窗口示意图:

    分成了四个部分,分别是(其中那个黑模型就是滑动窗口):

    1. 已收到ack确认的数据。
    2. 已发出但还没收到ack的。
    3. 在窗口中还没有发出的(接收方还有空间)。
    4. 窗口以外的数据(接收方没空间)。

  • 下面是个滑动后的示意图(收到36的ack,并发出了46-51的字节):

滑动窗口中窗口前段为已发送但为收到ACK的数据,后段为待发送数据。

  • 发送端一次发送多个数据,接收端回传收到的连续数据的ACK信号,缓存缺失数据之后的数据包(保持顺序)。
  • 当发送端收到ACK信号时,窗口向前依次移动,直到遇到有数据未确认时停止。
  • 一段时间后启动超时重传,接收端若收到缺失数据,则和缓存数据一起发送ACK信号,否则,抛弃缓存数据。

2.6 流量控制

接收端在接收到数据后,对其进行处理。

  • 如果发送端的发送速度太快,导致接收端的结束缓冲区很快的填充满了。此时如果发送端仍旧发送数据,那么接下来发送的数据都会丢包,继而导致丢包的一系列连锁反应,如超时重传。

而TCP根据接收端对数据的处理能力,决定发送端的发送速度,这个机制就是流量控制。

简单来说就是接收方处理不过来的时候,就把窗口缩小,并把窗口值告诉发送端。

  • TCP首部有一个字段来通知窗口的大小,接收端通过设置来主动控制传输流量。
  • 如果接收到窗口大小的值为0,那么发送方将停止发送数据,并定期的向接收端发送窗口探测数据段,让接收端把窗口大小告诉发送端。

2.7 拥塞控制

  • 如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。
    • 这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度
  • 发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口

发送端通过拥塞窗口主动控制传输流量。主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。

  • 慢开始:防止双方通信刚开始就传送大量数据包,发送端拥塞窗口初始设置为1MSS(以报文段而非字节为单位),每接受一个ACK信号,窗口扩大为两倍。

    • 发送数据时,取拥塞窗口和滑动窗口的较小值。同时设定一个慢启动阈值,初始值设置为16个报文段,即ssthresh=16。

  • 拥塞避免

    • 一开始以慢开始算法(指数增长)。当cwnd=16时开始执行拥塞避免算法,呈现线性增长。
    • 当拥塞窗口cwnd=24时出现超时,发送方判定为网络拥塞,于是调整门限值ssthresh=cwnd/2=12,同时设置拥塞窗口为1,进入慢开始阶段。
    • 按照慢开始算法,发送方每收到一个新报文段的确认ACK拥塞窗口值增加。当cwnd=12时(图中点3)执行拥塞避免算法。

TCP以段为单位发送数据包:在建立TCP连接的同时,两端协商发送数据包的单位,称为“最大消息长度”:MSS。

  • 【TCP数据(MSS字节)】【TCP首部(20字节)】【IP首部(20字节)】
  • 快重传和快恢复
    • 当cwnd=16时(图中点4)出现了一个新的情况,就是发送方连续收到3个对统一报文段的重复确认(3-ACK)。发送方执行快重传和快恢复算法。
      • 在图中点4,发送方知道只是丢失了个别的报文段,于是不启动慢开始,而是先进行快重传然后执行快恢复算法。
      • 发送方设置调整门限值ssthresh=cwnd/2=8, 同时拥塞窗口cwnd=ssthresh=8(点5),然后进行拥塞避免算法。
    • 快重传:收到3个同样的确认就立刻重传特定的报文,不等到超时。
    • 快恢复:cwnd不是从1重新开始。


【部分内容参考自】

  • 《计算机网络–自顶向下方法》
  • 《TCP/IP详解 卷1:协议》
  • TCP的三次握手和四次挥手:https://www.cnblogs.com/xiaokang01/p/10032377.html
  • TCP实现可靠传输:https://www.cnblogs.com/walker993/p/9570902.html
  • TCP协议如何保证可靠传输:https://www.cnblogs.com/xiaokang01/p/10033267.html

以上是关于计算机网络测试人关于TCP的学习和梳理的主要内容,如果未能解决你的问题,请参考以下文章

计算机网络测试人关于HTTP的学习和梳理

计算机网络测试人关于HTTPS的学习和梳理

计算机网络测试人关于HTTPS的学习和梳理

计算机网络测试人关于计算机网络的学习和梳理

TCP拥塞控制

计算机网络—— 运输层:TCP报文段的首部格式