Skip to content

05 运输层

第五章 运输层

统计信息:字数 16231 阅读33分钟

P57 5.1 运输层概述

物理层,数据链路层,网络层解决了异构网络中不同主机的通信,实际上计算机通信的实体是主机中独立的进程。

运输层解决的就是不同主机上的进程之间的通信(端到端协议)。网络层已经解决了底层的通信问题,给上层的运输层的逻辑通信提供服务。

运输层为应用层提供了两个协议:面向连接的 TCP 和 无连接的 UDP 协议。

P58 5.2 运输层端口号、复用与分用

运输层端口号

进程端口号:一个计算机上的进程使用进程端口号(PID)标识。不同操作系统中的进程需要通信,所以需要定制统一的规范。 运输层使用端口号区分不同的应用进程。端口号只在本机起到进程的识别,在不同计算机中,相同端口号之间没有联系。

端口号使用16比特表示,取值是0-65535。分成三类:

  • 熟知端口号(世界范围内通用的端口号,HTTP 80端口,DNS 53端口);
  • 登记端口号(微软到官方机构,登记一下,使用 3389 作为微软远程桌面使用的端口号,MySQL 数据库登记某个端口等等)
  • 短暂端口号(客户端和服务器通信时,会约定一个临时的动态端口,通信结束后,可以释放这个端口号,供其他客户进程使用)

端口复用和分用

发送方的端口号复用,接收方的端口号分用。发送方:多个进程通过某个相同的运输层端口通信(不同时或者同时),就是发送方的端口号复用。接收方:某个运输层端口获取到报文后,然后分发给不同的进程,就是接收方的报文分用(不同时或者同时)。

UDP 用户数据报使用 17 协议字段;TCP 报文段使用 6 协议字段。

实例(网络请求)

1、浏览器向 DNS 服务器发送请求(baidu.com的IP是什么),UDP 源端口 49152,目的端口 53。运输层将 UDP 用户数据包封装到 IP 数据报。

2、DNS 服务器接收到报文后,响应报文源端口 53,目的端口 49152,发送 DNS 解析后的结果。

3、浏览器接收到报文,获取 IP 地址,然后使用 HTTP 请求,将TCP报文段封装到 IP 数据报中,源端口 49152,目的端口 80 ,报文内容是 baidu.com/index.html

4、百度服务器接收后,相应报文源端口 80,目的端口 49152,返回相应报文。

5、浏览器收到报文,完成请求操作。

期间客户端的 49152 端口实现了端口复用。

P59 5.3 UDP和TCP的对比-重点

UDP,User datagram Protocal 用户数据报协议

TCP,Transmission Control Protocal 传输控制协议

主要区别:

  • 连接:UDP 直接无连接,TCP 面向连接,需要三次握手四次挥手。

  • 通信数量:UDP 支持单播多播广播,TCP 仅支持单播。

  • 传输单位:UDP 面向应用层报文(传输过程中,保留报文的边界)。TCP 是面向字节流(实现可靠传输)
  • 可靠性:如果传输有误码,UDP 向上提供无连接不可靠的传输服务,接收方获取误码的报文,仅仅丢弃,其他什么都不做(不可靠),主要适用于IP电话或者视频会议等实时应用(偶尔丢包造成视频掉帧,不会有特别大的影响)最大努力交付,不使用流量控制和拥塞控制。TCP 是可靠信道,不会出现传输差错(误码,丢失,乱序,重复等),适用于可靠传输的应用,例如文件传输(出错了,文件就不能用了),使用流量控制和拥塞控制。
  • 首部长度:UDP仅8字节,开销小(源端口,目的端口,长度,校验),TCP 报文首部字段最小20字节,最大60字节(增加了确认好,窗口,选项等参数)

P60 5.4 TCP的流量控制

通常我们希望数据传输的更快一些,如果发送方把数据发送的过快,接收方可能老不及接收,就会造成数据的丢失。

流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接收。利用滑动窗口算法,可以在 TCP 连接上实现发送方的流量控制。

例子:AB两个主机建立 TCP 连接,A是发送端,B是接收端,B对A实现流量控制,下面是流量控制过程:

  • A主机默认的发送窗口区间是400
  • A主机发送了300字节数据
  • B主机接收到前200字节数据,将200字节确认,最后100字节数据丢失了
  • B主机流量控制:将接收窗口区间改成300,对主机A进行流量控制(ACK=1,ack=201, rwnd=300)ACK=1 表示确认报文段,ack 表示从201开始接收,rwnd 是接收方的窗口区间是300
  • A主机调整发送窗口区间到300(可以发送201-500的数据),那么先发送300-400,400-500的数据,然后超时重传旧的200-300的数据(不能发送新的数据了)
  • B主机接收到200-500的数据后,累计确认,将接收窗口改成100(ACK=1, ack = 501, rwnd = 100)
  • A主机接收到ACK报文,将发送窗口区间改成100,向右滑动窗口,发送500-600数据
  • B主机收到600后,把接收窗口改成0(假设B主机的栈内存临时用完了,不能接收新的数据报文了)
  • A主机把发送窗口改成0,不能再发送数据了。

特殊情况

  • 如果B主机内存有了,将接收窗口改成300,发送给主机A,但是丢包了。此时A主机等待B主机的非零窗口通知,B主机等待A主机发送数据,就形成了死锁
  • TCP为每一个连接设置一个持续计时器。当持续计时器超时,A主机发送零窗口探测报文(如果B主机还没有内存,就告诉A主机窗口是0)如果没有回复,就断开 TCP 连接。

P61 5.5 TCP的拥塞控制

拥塞:网络中资源供小于求,网络资源指的是(带宽,交换节点中的缓存和处理机等)。如果拥塞不控制,造成网络性能变差,网络吞吐量随着输入负荷增大而下降。

理想的吞吐量和输入负载成正比(输入负载增加,吞吐量增加);实际上拥塞时,吞吐量会大大下降(网络中某些分组被某个节点丢弃)。轻度拥塞时,载入负荷还是和吞吐量正相关。如果无拥塞控制,最后死锁,吞吐量为0,所以需要 TCP 拥塞控制。

拥塞控制四种算法:慢开始、拥塞避免、快重传、快恢复。

讨论拥塞控制时,忽略下面的情况:TCP 假设单向传播,另一个方向确认;接收方和发送方缓存足够大,发送窗口的大小由网络的拥塞程度决定;以MSS最大报文段讨论

慢开始和拥塞控制

发送方用 cwnd 拥塞窗口(取决于网络的拥塞程度,动态变化)。只要网络不拥塞,拥塞窗口就增大。当网络出现拥塞,拥塞窗口就减小。

判断网络拥塞的依据:出现超时重传(没有按时收到应当到达的确认报文)

发送方设置 swnd 发送窗口 = cwdn 拥塞窗口

发送方设置一个慢开始门限 ssthresh 当拥塞窗口小于慢开始门限,使用慢开始算法。当拥塞窗口大于 ssthresh 采用拥塞避免算法。当两者相等,两种算法都可以。

例子:慢开始算法,就是N秒传递速度是N-1秒的2倍(2^n),指数规则增加。到达慢开始门限后,使用拥塞避免算法(正比例函数,每次比前一次增加1)

当超时重传时,1、将慢开始门限设置为发生拥塞时拥塞窗口的一半。2、将拥塞窗口减少为1,并重新开始慢开始算法。

慢开始指的是开始很慢(注入的报文段少),并不是增长速度慢。

拥塞避免,并不能完全避免拥塞,而是把拥塞避免算法阶段,把拥塞窗口控制为线性增长,使得网络不容易出现拥塞。

这个算法有例外情况:如果个别报文段丢失,造成超时重传(实际网络没有发生拥塞),这也会成发送方误认为网络拥塞,并更改慢开始门限值和拥塞窗口 = 1,这样降低了传输效率。那么就出现了下面的算法。

快重传和快恢复

这两个算法可以改进 TCP 的性能

快重传:让发送方尽早知道个别报文段的丢失,而不是等超时重传计时器超时后才重传报文。要求接收方接收到报文后,不要等自己发送数据时,才捎带确认,而是要立刻发送确认报文。即使收到了失序的报文,也要对已经收到的报文段重复确认。发送方收到3个连续的重复确认,不需要考虑超时重传计时器,直接将相应的报文段立即重传。这样就避免了网络丢包,而不是网络拥塞造成的问题(不会造成超时重传计时器到时间 RTO)。

快恢复算法:发送方如果收到3个重复的确认,说明丢失了个别报文段,不启动慢开始算法,执行快恢复算法。发送方将慢开始门限 ssthresh 和 拥塞窗口 cwnd 值调整为当前窗口的一半,开始执行拥塞避免算法。也有的改成 新的ssthresh + 3(因为有3个重复的确认,已经有3个报文字段离开了网络)最好看图示

P62 5.6 TCP超时重传时间的选择

往返时间 RTT,超时重传时间 RTO,这个和网络性能影响很大。RTO 应该略大于 RTT。实际网络中,RTT 的值是变化的,所以 RTO 也是需要动态计算的,所以这个问题很复杂。

加权平均往返时间 RTTs = (1-a)* RTTs(old) + a * RTT, a 通常是 0.125。RTO 应该略大于 RTTs(这个值更加平滑)

改进后的算法 RTO = RTTs + 4 * RTTd(偏差值得加权平均)

实际上,RTT 测量也比较复杂(如果存在报文的丢失或者重传,计算值就变化)。Karn 算法:如果出现报文重传,不计算这次的 RTT。改进算法:重传一次,把RTO增大一些(典型算法是变成原来的2倍)

P63 5.7 TCP可靠传输的实现

TCP基于字节传输,算法是滑动窗口,发送窗口 = min(接收窗口,拥塞窗口)

使用三个指针 p1p2p3 进行滑动窗口

  • p1 表示已经发送并确认收到的部分(增加,不变)
  • p3 表示可以发送的部分 (p3-p1就是发送窗口)(增加,不变,或者减少——TCP不建议)
  • p2 在中间,表示可以发送的部分中,已经发送,但是还没有确定收到的部分(p3-p2 有效窗口或者可用窗口)

通常情况下,p1 p2 p3 都不断向前移动。当报文丢失或者发送窗口减小时,调整p1的指向对应的字节序号,实现可靠传输。

可靠传输的实现

  • 发送窗口根据接收窗口设置,但是某个时刻,这两个窗口不一定相等(时延,拥塞)
  • 如果数据不按序到达,接收方先放到临时窗口中,等前面的接收后,按序交付给上层
  • 接收方需要累计确认和捎带确认(减小传输开支)不应该过分延迟确认报文
  • TCP是全双工通信。双方都有发送窗口和接收窗口,需要区分。

P64 5.8 TCP的运输连接管理—TCP连接建立-三次握手

TCP面向连接的协议(TCP报文段)需要三次握手建立连接;传输数据;四次挥手断开连接

TCP 通过三次握手建立连接,目的是让双方都知道存在,协商传输参数(最大窗口值,窗口扩大选项)

TCP服务端和客户端进程先都打开,服务端监听消息

1、客户端发送 TCP 连接请求(SYN=1,seq=x)进入同步已发送状态

2、服务器收到后,进入同步已接收状态,发送 SYN = 1,ACK = 1 seq=y, ack = x+1

3、客户端收到后,进入连接已建立,ACK=1,seq = x + 1, ack = y + 1,服务端收到后建立连接(ack是对上一个seq的确认,ack = seq + 1)

第三次连接不能少的原因:如果第一次连接A发送后,延迟了。又发出了一个连接B,这个连接建立后并释放后,A连接才到达服务端,这样服务端会继续打开,浪费服务端的性能。所以需要第三次连接(为了防止失效的连接请求突然传到服务端,造成错误)。

注意:

1、SYN=1的报文段,不能携带数据,但是消耗一个序号

2、普通的确认报文段,如果不携带数据,不消耗序号

P65 5.8 TCP的运输连接管理—TCP连接释放-四次挥手

TCP 通过4报文挥手实现连接释放(断开连接)

1、客户端主动关闭数据传输,发送第一个报文(我已经不发送报文了,可以接收)

2、服务器收到后,发送一个响应报文(好的,服务器端知道了)此时服务器端还可以发送数据。

3、当服务器发送完报文后,被动关闭,发送一个报文(服务端要关闭了)

4、客户端接收到报文后,发送给服务端确认报文(服务端可以关闭了)

5、服务端关闭。客户端等待4分钟后(2MSL,最长报文段寿命,通常是4分钟)关闭状态。

客户端等待2MSL的必要性:避免客户端最后一个报文中途丢失,造成服务端继续发送超时重传报文,造成服务端性能浪费。

保活计时器:TCP服务器端收到数据后,重置报活计时器。如果客户端出现故障,无法发送报文。那么报活计时器一定时间后没有收到数据,就向客户端发送探测报文段,每隔75s发送一个探测报文段。如果发送10个探测报文段无响应,服务器进程就认为客户端进程所在主机故障了,关闭这个TCP连接。

P66 5.9 TCP报文段的首部格式

TCP 可靠传输基于面向字节流:发送数据时,从发送缓存中取出全部或者部分数据,然后给其加一个首部成为 TCP 报文段。TCP 的全部功能体现在首部的各字段中。

TCP报文段 = 首部+数据载荷

首部 = 固定首部(20字节)+扩展首部(小于40字节)

首部格式字段

  • 源端口(例如浏览器进程端口号49152)
  • 目的端口(例如服务器端口号80)
  • 序号(当前TCP报文段中,数据载荷的第一个字节的序号) 超出 2^32 后重置为0
  • 确认号N:对之前所有收到数据的确认,已经收到N-1之前全部数据(已经正确接收),期望收到下一个TCP序号是N
  • ACK 确认标志位:如果是1,确认号字段有效;如果是0,确认号字段无效。TCP 规定,连接建立后,所有传送的TCP报文段 ACK 必须是1.
  • 数据偏移:4比特;以四字节为单位。因为TCP报文段有扩展首部,所以首部长度不确定。这个字段指出了TCP报文段的首部长度(TCP数据载荷部分的起始位置距离TCP报文段的起始处的位置)如果TCP首部是20字节,那么数据偏移是 0101,如果首部是 40 字节,那么数据偏移是 1111
  • 保留:目前是0,以后使用
  • 窗口:发送方的接收窗口,接收方根据这个字段,设置发送窗口,进行流量控制。实际上发送窗口 = min(接收窗口,拥塞窗口)
  • 校验和:16比特,检查TCP报文段的首部和数据载荷部分(检测是否有误码等)
  • SYN(sync):同步标志位,用于TCP连接建立时同步序号(三次握手需要SYN字段)
  • FIN(finish):终止标志位,用于释放TCP连接(四次挥手需要FIN字段)
  • RST(reset)复位TCP,如果是1,表示TCP连接异常,需要释放连接并重新建立
  • PSH(push)推送标志位,如果是1,接收方需要尽快上交报文给上层进程,不需要等待接收缓存都填充后再交付。
  • URG(urgent) 紧急标志位,如果是1,紧急指针字段有效
  • 紧急指针:表明紧急数据的长度。如果发送方有紧急数据,可以将紧急数据插队放到最前面,立即分装成TCP报文段发送。紧急指针表示,本报文中数据载荷中有N长度的紧急数据,后面是普通数据。
  • 其他字段:最大报文段长度MSS(数据载荷最大值),窗口扩大选项(提高吞吐率);时间戳(计算RTT);选择确认选项等。
  • 填充:因为其他字段长度可变,为了确保报文段能被4整除(数据首部长度是以4字节为单位的)用空白值填充长度

例如一个报文:序号201;数据载荷长度100字节;确认号800,ACK是1


Last update: November 9, 2024