计算机网络——传输层

传输层

运输层概述

从通信和信息处理的角度看,运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是用户功能中的最底层

从运输层角度看,通信的真正端点是主机上的进程而不是主机,也就是说,端到端的通信是指应用进程之间的通信

运输层提供的是一种逻辑通信而非物理通信:运输层协议为运行在不同主机上的应用进程之间提供逻辑通信功能,而无须考虑承载这些报文的物理基础设施的细节。

复用和分用

运输层有一个非常重要的功能,即复用和分用

  • 复用:发送方不同的应用进程都可以使用同一个运输层协议传输数据,前提当然是要加上适当的首部。
  • 分用:接收方的运输层在剥去报文的首部后能够把这些数据正确交付给目的进程。

运输层和网络层的关系

运输层只工作在端系统中,负责将来自应用进程的报文移动到网络边缘(即网络层),以及将来自网络边缘的报文移动到应用进程中。中间路由器既不处理也不识别运输层加在应用层报文的任何信息。

网络层是为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。

网络层只校验IP数据报首部是否出错,而不检查数据部分,运输层提供对接收到的报文进行差错校验

网络层的服务模型是尽力而为交付服务,不确保报文段的交付,不保证报文段的按序交付,不保证报文段中数据的完整性。

运输层的两个主要协议

UDP(User Datagram Protocol,用户数据报协议):不可靠、无连接

TCP(Transmission Control Protocol,传输控制协议):可靠、面向连接

端口号

因为一台主机上可能运行着多个应用进程,为了能准确识别一台主机上的不同进程,我们使用端口号作为其唯一标识。

端口号由2个字节16位组成,可允许有65535个不同端口号,由于端口号只具有本地意义(即允许不同主机上存在相同的端口号),因此这个数目对于一个计算机来说是足够使用的。

端口号可分为以下两大类:

  • 服务端使用的端口号:
    • 熟知端口号:0~1023,其使用是受限制的,只保留给诸如HTTP(80)、FTP(21)之类的周知应用层协议使用。
    • 登记端口号:1024~49151,这类端口号是为没有熟知端口号的应用程序使用。
  • 客户端使用的端口号:49152~65535,由于这类端口号仅在客户进程运行时才动态选择,因此又叫短暂端口号。这种短暂端口号一般是由操作系统动态进行分配的。

UDP

概述

UDP只在IP数据包服务的基础上增加了很少一点的功能,即复用和分用、以及差错校验。其特点如下:

  1. 无连接。发送数据前无需建立连接,减少了开销和发送数据之前的时延。
  2. 尽最大努力交付。不保证可靠传输,因此也不需要维护复杂的连接状态表。
  3. 面向报文传输。对应用程序交下来的报文,在添加首部后就向下交付给IP层。因此如果交付给IP层的报文过长,IP在传送时需要进行分片,这会降低IP层的效率。
  4. 没有拥塞控制
  5. 支持一对一、一对多、多对一、多对多的交互通信
  6. 首部开销小。只有8个字节

首部格式

UDP首部由四个字段组成,每个字段两个字节,各字段意义如下:

  1. 源端口号。需要对方回信时选择用,不需要时可用全0。
  2. 目的端口号。交付的终点,必需。
  3. 长度。UDP用户数据报的长度,其最小值为8(仅有首部)。
  4. 校验和。检测UDP用户数据报在传输中是否有错,有错就丢弃。

TCP

概述

TCP最主要的特点:

  1. 面向连接。发送数据前需要先建立连接。
  2. 只支持一对一通信
  3. 提供可靠交付服务。通过TCP连接传送的数据,能够无差错不丢失不重复、并且按序到达。
  4. 提供全双工通信。TCP允许通信双方在任何时候都能发送数据。
  5. 面向字节流。流指的是流入到进程或从进程流出的字节序列。

Socket

TCP连接的端点叫做Socket。

套接字Socket = (IP地址 : 端口号)

每一条TCP连接能都唯一被通信两端的两个端点(即两个套接字)所确定:

TCP连接 = {Socket1, Socket2} = {(IP1 : Port1), (IP2:Port2)}

Socket这个词有很多不同的意思,例如:

  1. 应用层和运输层之间的一种网络应用编程接口API,成为 Socket API,简称Socket。
  2. 在Socket API中使用的一个函数名也叫Socket。
  3. 调用Socket函数的端点称为Socket,如“创建一个数据包Socket”。
  4. 调用Socket函数时,其返回值称为Socket描述符,可简称为Socket。
  5. 在操作系统内核中连网协议的Berkeley实现,称为Socket实现。

此处所提到的Socket是指IP地址和端口的拼接。

可靠传输原理——超时重传

可靠传输主要通过滑动窗口机制和超时重传机制来实现,先简单看一下什么是超时重传。

为了方便描述数据传输的过程,将发送方记为A,接收方记为B,传输的数据单元称为分组。

现在考虑以下两种可能出现差错的情况:

  • A发送的分组在发送过程中丢失,B没有接收到分组,因此A也不会接收到B的确认分组。
  • B的确认报文在返回途中丢失,A没有接收到确认分组。

为了解决上述两个问题,TCP协议使用一种超时重传机制:A只要超过一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,会重传前面发送过的分组。

要实现超时重传,就要在每次发送完分组后设置一个超时计时器,如果在超时计时器到期之前收到了对方的确认,就撤销已设置的超时计时器,否则重传数据并重置超时计时器。

实现可靠传输需要注意以下几点:

  • A发送完一个分组后,必须暂存一发送的分组的副本,为超时重传时使用。
  • 分组和确认分组都必须进行编号。
  • 超时计时器设置的重置时间应当比数据在分组传输的平均往返时间更长一些。

连续ARQ协议

ARQ的含义:自动重传请求,Automatic Repeat Request。重传请求是由发送方自动进行的,接收方不需要请求发送方重传某个出错的分组。

假设每发送一个分组都停止等待,直接收到确认分组后再发送下一个分组,这样的信道利用率太低了。因而TCP采取的是可连续发送滑动窗口内的多个分组,接收方采用一种累积确认的方式。

累积确认:接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,表示这个分组之前的所有分组都已经正确收到了。

累积确认的优缺点:

  • 优点:容易实现,即使确认丢失也不必重传

  • 缺点:不能向发送方反映出接收方已经正确收到的所有分组的信息。

    例如,如果发送方发送了前5个分组,而中间的第3个分组丢失了。这时接收方只能对前两个分组发出确认。发送方无法知道后面三个分组的下落,而只好把后面的三个分组都再重传一次。这就叫做Go-back-N(回退N),表示需要再退回来重传已发送过的N个分组。可见当通信线路质量不好时,连续ARQ协议会带来负面的影响。

TCP首部格式

img

  1. 源端口号目的端口号,各占2个字节。
  2. 序号。4个字节,范围是 [ 0 , 2 32 − 1 ] [0, 2^{32}-1] [0,2321],序号增加到 2 32 − 1 2^{32}-1 2321后,下一个序号就又回到0。由于TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。例如,一报文段的序号字段值是301,而携带的数据共有100字节。这就表明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。下一个报文段的数据序号应当从401开始。
  3. 确认号。4个字节,表示期望收到对方下一个报文段的第一个数据字节的序号,同时也表示该确认号之前的所有数据都已经正确接收到了。
  4. 数据偏移。占4位,指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。由于首部中还有长度不确定的选项字段,因此数据偏移字段是必要的。但应注意,“数据偏移”的单位是32位字(即以4字节长的字为计算单位)。由于4位二进制数能够表示的最大十进制数字是15,因此数据偏移的最大值是60字节,这也是TCP首部的最大长度(即选项长度不能超过40字节)
  5. 保留。占6位,保留为今后使用,但目前应置为0。
  6. 6个控制位
    • 紧急URG (URGent) 当URG = 1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序来传送。
    • 确认ACK (ACKnowlegment) 仅当ACK = 1时确认号字段才有效。当ACK = 0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。
    • 推送PSH(PuSH)当PSH为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
    • 复位RST (ReSeT)当RST = 1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。还可以用来拒绝一个非法的报文段或拒绝打开一个连接。RST也可称为重建位或重置位。
    • 同步SYN (SYNchronization) 在连接建立时用来同步序号。当SYN = 1而ACK = 0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN = 1和ACK = 1。因此,SYN置为1就表示这是一个连接请求或连接接受报文。
    • 终止FIN (FINish)用来释放一个连接。当FIN = 1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接。
  7. 窗口。占2个字节,窗口指的是发送本报文段的一方的接收。窗口字段明确指出了现在允许对方发送的数据量。窗口值是经常在动态变化着。窗口单位是字节,不是报文段。
  8. 检验和 。占2字节。检验和字段检验的范围包括首部和数据这两部分。和UDP用户数据报一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。
  9. 紧急指针 。占2字节。紧急指针仅在URG = 1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。
  10. 选项 。选项的长度可变,最长可达40字节。当没有使用“选项”时,TCP的首部长度是20字节

一些可能用到的选项:

  • MSS:最大报文长度,Maximum Segment Size。指的是每一个TCP报文段中的数据字段的最大长度(不包括首部在内的长度)。MSS应尽可能大些,只要在IP层传输时不需要再分片就行。在建立连接时双方可以在选项中写入支持的MSS,若主机未填写这一项,MSS的默认值为536字节。
  • 窗口扩大选项:占3个字节,默认的窗口是2个字节,在某些场景下例如包含卫星信道的网络中,传播时延和带宽都很大,要获得高吞吐率需要更大的窗口大小。
  • 时间戳选项:占10个字节,其中最主要的字段时间戳值字段(4字节)和时间戳回送回答字段(4字节)。时间戳可用来:
    • 计算往返时间RTT。
    • 处理TCP序号超过 2 32 2^{32} 232的情况,也叫防止序号绕回 PAWS (Protect AgainstWrapped Sequence numbers)。

TCP可靠传输的实现——滑动窗口

发送方采用滑动窗口机制,在发送缓存中维护一个发送窗口,具体发送窗口大小由对方返回的TCP报文首部的窗口字段来确定。

A可以连续把窗口内的数据都发送出去,凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。只有接收到B返回的确认后,才会将发动窗口往前移动(同时将已被确认的数据从发送缓存中删除)。

需要注意以下几点:

  • 虽然A的发送窗口是根据B的接收窗口来设置的,但在同一时刻,A的发送窗口并不总是和B的接收窗口一样大,这是因为网络传送窗口值有一定的时延。
  • 对不按序到达的数据如何处理,TCP标准没有明确的规定。如果接收方把不按序到达的数据一律丢弃,那么接收窗口的管理将会比较简单,但这样做对网络资源的利用不利(因为发送方会重复传送较多的数据)。因此TCP通常对不按序到达的数据是先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程。
  • TCP要求接收方必须有累积确认的功能,这样可以减少传输开销。接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。但请注意两点,一是接收方不应过分推迟发送确认,否则会导致发送方不必要的重传,这反而浪费了网络的资源。二是捎带确认实际上并不经常发生,因为大多数应用程序不同时在两个方向上发送数据。

超时重传时间的选择

超时重传时间不宜过短,否则会导致不必要的重传,浪费网络资源。超时重传时间也不宜过长,不然会导致网络空闲时间增大,降低了传输效率。

TCP采用了一种自适应算法,记录每个报文段的往返时间RTT(RTT为从发出报文到收到确认的这一段时间),根据RTT的变化来更新超时重传时间RTO(Retransmission Time-Out),具体计算公式如下:
R T O = R T T S + 4 × R T T D RTO = RTT_S + 4 \times RTT_D RTO=RTTS+4×RTTD

  • $ RTT_S$是加权平均往返时间:
    R T T S = ( 1 − α ) × ( R T T S ) + α × ( R T T ) RTT_S = (1 - \alpha) \times (RTT_S) + \alpha \times (RTT) RTTS=(1α)×(RTTS)+α×(RTT)
    α \alpha α的范围为 0 ≤ α < 1 0 \le \alpha \lt1 0α<1,当 α \alpha α接近于零时,表示新的$ RTT_S 和 旧 的 和旧的 RTT_S 变 化 不 大 , 当 变化不大,当 \alpha 接 近 于 1 时 , 表 示 新 的 接近于1时,表示新的 1 RTT_S 受 新 的 R T T 样 本 影 响 较 大 。 T C P 推 荐 的 受新的RTT样本影响较大。TCP推荐的 RTTTCP\alpha$值为1/8,即0.125。

  • $ RTT_D$是RTT的偏差的加权平均值:
    R T T D = ( 1 − β ) × R T T D + β × ∣ R T T s − R T T ∣ RTT_D = (1-\beta) \times RTT_D + \beta \times |RTT_s - RTT| RTTD=(1β)×RTTD+β×RTTsRTT
    第一次测量时, R T T D RTT_D RTTD取RTT的一般, β \beta β的推荐值为1/4,即0.25。

由于超时重传发生后,发送方无法确定确认报文是对原来报文段的确认还是对重传报文段的确认,这会导致计算出来的RTO偏大或者偏小,解决办法是:发生超时重传是,按在按照RTO的计算公式去计算超时重传时间,而是当报文段每重传一次,就把RTO增大一些(典型做法是增大2倍, 2 × R T O 2\times RTO 2×RTO),当不再发生报文段重传后,才根据RTO的计算公式去计算超时重传时间。

选择确认SACK

考虑一个问题:接收方收到的报文段序号不连续,比如序号1 - 1000和序号1501 - 2000的报文段收到了,唯独序号1001 - 1500的报文段没收到,有没有办法让发送方只传送缺少的数据(序号1001 - 1500)而不重传已经确定到达接收方的数据(序号1501 - 2000)。

选择确认SACK(Selective ACK)就是解决上述问题的一种方法。

SACK返回一个确认块,分别是左边界和右边界,表示这个区间内的报文段都已正确接收到了。

使用SACK的前提是双方都要在首部选项中增加SACK选项。

由于首部选项最多支持40个字节,使用SACK首先需要2个字节,一个用来指明是SACK选项,另一个字节用来指明这个SACK选项占用多少个字节。因此首部最多还剩下38个字节可用,由于一个确认号占用4个字节,一对确认号(左右边界)就占8个字节,因此,最多支持SACK的确认块为4个。

TCP的流量控制

流量控制:接收方通过返回确认报文中的窗口字段,控制发送方的发送窗口大小,使其发送窗口大小不能超过接收方给出的接收窗口的数值。

考虑这样一种情况:但B接收缓存已满时,B给A发送了一个零窗口的报文段,但不久后,B的接受缓存又有了一些存储空间,于是B给A发送一个确认报文告诉A当前的接收窗口大小,但不幸的是这个确认报文在发送过程中丢失了,这样导致了A等待B窗口非零的通知,而B也在等待A发送报文的死锁场面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值