4545 字
23 分钟
网络原理: 运输层

更新于2024-05-30 20:04:52

1. 运输层的作用#

1.1 运输层的作用#

TIP

运输层向它上面的应用层提供通信服务,它是面向通信部分的最高层,是用户功能的最底层

TIP

网络通信的两个端点是两台主机的进程

运输层一个很重要的作用是复用(multiplexingmultiplexing)分用(demultiplexing)demultiplexing)

运输层还需要对报文进行差错检测

和一般的网络分层次一样,运输层为上层屏蔽了下面网络核心的细节,它使上层也只看见数据在两台主机的运输层平行传输。

定义1.1.11.1.1 两个对等运输实体在通信时传送的数据单元叫做运输协议数据单元(Transport Protocol Data Unit)TPDU,对应在TCP/UDP协议下叫做TCP数据段(segmentsegment)/UDP用户数据报。

1.2 运输层的端口#

需要有一种和操作系统无关的方式来标识主机间的进程,这种方式也就是在运输层使用协议端口号(Protocol Port Number)。数据报被传送到某台主机运输层的端口上,接着由运输层完成分用,把该数据交给对应的进程。

TCP/UDPTCP/UDP的端口都使用1616位二进制数0655350-65535,端口号只具有本地意义,是应用层各个进程和运输层交互的一个层间接口。是一个软件接口

其中110231\sim 1023叫做**熟知端口号(well-known port number)**或者系统端口号,固定分配给一些特定的应用进程。

1024491511024\sim 49151 叫做登记端口号,给没有熟知端口号的服务器进程使用

491526553549152\sim 65535叫做短暂端口号,一般给客户端进程暂时动态选择使用。

2. UDPUDP#

2.1 UDPUDP的特点#

UDPUDP的特点主要有:

  1. UDPUDP无连接的协议,发送数据之前无需连接,也不需要关闭连接
  2. UDPUDP尽最大努力交付的,不保证可靠地交付
  3. UDPUDP面向报文的,每当上层交付一个数据报文,加上头部后就直接交付给IPIP。不拆、不合并,不改变该数据报文的边界。每当从IPIP层接收一个数据报,去掉头部后就直接交给上层。一次交付一个完整的报文。
  4. UDPUDP没有拥塞控制功能。
  5. UDPUDP支持一对一、一对多、多对一、多对多的通信方式。
  6. UDPUDP的头部开销非常小,只占**88个字节**。
CAUTION

由于UDPUDP面向报文,因此上层交给UDPUDP传输的报文必须要控制好大小。太大的报文在UDPUDP交给IPIP层时,IPIP层一定要经过分片,效率很低。太小的报文会使得报文首部的比例占比过大,导致传输效率不高。

TIP

UDPUDP没有拥塞控制,这意味着即便网络拥塞时数据的传输速率也不会变小。一方面这对实时性应用进程是好事,但是另一方面没有拥塞控制的UDPUDP可能会引起网络的严重拥塞问题。

另外应用进程可以根据自己的需要,在传输层的上层为UDPUDP自行添加一些提高可靠性的措施

2.2 UDPUDP报文的格式#

UDPUDP报文的首部非常小,只有88字节。

位数/字节数
源端口16/216/2
目的端口16/216/2
长度16/216/2整个UDPUDP数据报的长度,最小值是88字节
校验和16/216/2加上伪首部的反码校验和,校验整个数据报
伪首部96/1296/12包括源IP,目的IP,0,17(协议字段),UDPUDP数据报长度
TIP

当接收方发现UDPUDP数据报中的目的端口并不可达时,就会发送ICMPICMP目的不可达的差错报告报文。(LinuxLinux下的TracerouteTraceroute)

CAUTION

UDPUDP差错校验的方法和IPv4IPv4首部校验使用的方式都是一样的,都是用1616位对齐反码的方式求校验和,并且带上了数据部分,因此当数据部分不是16位的时候,要在后面补0,凑16位。

3. TCPTCP#

3.1 TCPTCP的特点#

TCPTCP的主要特点有:

  1. TCPTCP是面向连接的,通信前需要建立连接,最后需要释放连接。
  2. TCPTCP提供可靠的交付服务
  3. TCPTCP面向字节流,而不是面向报文。即便应用进程和TCPTCP交互是一次一个数据块,但是TCPTCP只把这些数据视为一连串的无结构字节流
  4. TCPTCP拥有拥塞控制功能。
  5. TCPTCP只支持点对点、一对一的通信(TCPTCP​需要建立虚连接,有两个端点)。
  6. TCPTCP头部有2020个字节。
  7. TCPTCP​提供的通信是全双工的。
CAUTION

TCPTCP​协议的每一个端口都设有发送缓存和接收缓存,因此理论上进程可以在想发送的时候就发送,发送时也可以接收,是一条全双工的通信链路。

每当进程要发送数据时就会将数据放入发送缓存,接着进程就可以继续做自己的事情,由TCPTCP在合适的时候发送。[可能是等缓存满了、pushpush操作、超时]

因而面向字节流TCPTCP​并不能保证接收方收到的数据块和发送方发送的数据块的划分是一样的,但是接收方收到的字节流和发送方发送的一定是一致的。

接收方的接收进程一定要能识别这个被重新划分的字节流。

3.1.2 TCPTCP连接#

TCPTCP把连接作为最基本的抽象。

TCPTCP的连接是端点到端点的连接。每一个端点都是一个SocketSocket套接字,因此一个TCPTCP连接也可以表示为:

TCP连接:={Socket1,Socket2}={(IP1:Port1),(IP2,Port2)}TCP连接:=\{Socket_1,Socket_2\}=\{(IP_1:Port_1),(IP_2,Port_2)\}

也就是TCPTCP连接的四元组。

TCPTCP要建立的是可靠的通信信道,主要要实现的功能是:

  1. 信道不产生差错 [确认与重传机制]
  2. 发送方发送的数据接收方必须都能及时处理,(发送方和接收方的速度要匹配) [流量控制]

有一系列的协议用来解决这两个重要的问题。

3.2 TCPTCP报文的格式#

即便TCPTCP面向字节流,但是TCPTCP的传送单元也还是数据报,有首部,也有数据部分。

位/字节数说明
源端口16/216/2
目的端口16/216/2
序列号32/432/4TCPTCP报文段的数据部分的第一个字节的序号。数据部分的每一个字节都按顺序编号。Mod 232Mod \ 2^{32}
确认号32/432/4期待接收的下一个字符的顺序号。若顺序号=N=N,则表明前面到N1N-1为止的字节都已经收到了
数据偏移4/0.54/0.5标识数据字段的首部距离TCPTCP报文段距离多少个4字节。表示范围是[0,15]4[0,15]*4个字节。(60字节的最大首部长度)
紧急URG1/1/标识该报文是一个TCPTCP紧急报文,且此时紧急指针有效。等待队列里,TCPTCP会把紧急报文都插在一般报文的前面。
确认ACK1/1/ACK=1ACK=1确认号字段才有效。当建立连接后,所有报文的ACK都要被置为1。
推送PSH1/1/接收方收到PSH=1PSH=1的报文以后,会优先把此报文交给接收应用程序。
复位RST1/1/用来标识TCPTCP连接出错,需要先释放连接再重新连接。也可以用来拒绝一个非法的报文,或者是拒绝一次连接请求。
同步SYN1/1/用来建立连接。SYN=1,ACK=0SYN=1,ACK=0则为连接请求,SYN=1,ACK=1SYN=1,ACK=1则为连接接受。
终止FIN1/1/用来终止连接。FIN=1FIN=1表示本方要发送的数据都已经发送完毕了。
窗口16/216/2指示从该报文的确认字段号字节开始,对方(该报文的接收方)还能够发送windowwindow字节的数据。
校验和16/216/2校验和和UDPUDP一样加上1212字节的伪首部,协议字段改为66。(如果使用IPv6IPv6,则伪首部也要改变)。校验方法使用二进制反码运算。伪首部如图。
紧急指针16/216/2指出紧急数据的末尾在该报文中的位置/字节数(紧急数据都在一般数据之前),只有在URG=1URG=1时有效,且当窗口window=0window=0时也可以发送紧急数据!
选项0320/0400-320/0-40可变长,但一定是4字节的整数倍(否则填充)

TCP的伪首部

TIP

选项字段可以增加的选项有:

  1. 最大数据长度MSS(Maximum Segment Size)选项最大数据长度MSS(Maximum \ Segment \ Size)选项:单个TCPTCP报文数据部分的最大字节数,加上首部长度以后才会是TCPTCP报文的长度。在建立连接时,双方都把自己支持的MSSMSS写入报文段(可以不同),以后都按照这个MSSMSS传输。如果建立连接时没有MSSMSS选项,则默认MSS=536MSS=536字节。[因此每个主机能处理的TCPTCP报文段至少是536+20Byte536+20Byte]
  2. 窗口扩大选项窗口扩大选项[3ByteByte]: TCPTCP报文首部的窗口字段默认是1616位,而有些特殊状况下(卫星通信)需要扩大窗口值来提高吞吐量,此时可以用此选项扩大窗口值,该选项用一个字节SS(S14S\le 14)来表示位移值,则窗口字段的位数改为16+S16+S位,支持的最大窗口值为(216+S1)Byte(2^{16+S}-1)Byte。该选项也是在建立连接时协商,当不需要再使用窗口扩大以后,也可以利用该选项(SS设定为0)来取消窗口扩大。
  3. 时间戳选项时间戳选项[10Byte10Byte]: 选项中最主要的字段是时间戳值字段[4Byte]4Byte]时间戳回送回答字段[4Byte4Byte]
    • 计算RTT: 如果发送方先发送一个带有时间戳字段的时间戳选项,接收方确认后,把这个时间戳字段复制到确认报文的时间戳选项的时间戳回送回答字段中返回给发送方,发送方根据这个字段就很容易算出一个RTTRTT的时间(当前时间- 时间戳回送回答字段值)。
    • 防止序号绕回: 在报文里带上时间戳选项的时间戳字段,哪怕是当首部的序列号字段重复了(因为序列号是Mod 232Mod \ 2^{32}),也可以辨认的出这两个报文不是重复的报文。
  4. 选择确认选项SACK选择确认选项SACK[(2+8k)Byte(2+8k)Byte]:用来为**选择确认(Selective ACK)**机制提供服务。TCPTCP建立连接时由双方协商是否使用选择确认选项。选择确认选项中用44个字节表示出一个连续的字节块[44个字节表示字节块起始位置的序列号,44个字节表示出该字节块末位置的下一个字节的序列号],在使用另外的11个字节表示该选项是一个SACKSACK选项,再使用另一个字节表示该选项总共占用多少字节。因此总共使用(2+8k)(2+8k)个字节。由于选项字段的最大长度是4040字节,因此一个SACKSACK字段最多可以表示44个不连续的数据块。

3.3 TCPTCP可靠传输的实现方式#

3.3.1 TCPTCP的重传机制#

由于TCPTCP有超时重传机制,但是超多少时间TT才重传的时间TT很难确定。

TT过大导致接收方一直等待重传数据,空闲时间边长,效率很低

TT过小导致发送方不断进行不必要的重发,效率也很低。

希望这个TT仅仅只比往返时间RTTRTT稍微长一些。使用每一次往返报文的RTTRTT样本值来动态更新网络的往返时间RTTsRTT_s:

RTTS()=(1α)RTTS()+αRTTRTT_{S(新)} = (1-\alpha)\cdot RTT_{S(旧)} + \alpha\cdot RTT

一般取α=0.125\alpha = 0.125

也是用该样本RTTRTT更新往返时间的方差RTTDRTT_D:

RTTD()=(1β)RTTD()+βRTTS()RTTRTT_{D(新)} = (1-\beta)\cdot RTT_{D(旧)} + \beta \cdot |RTT_{S(新)} - RTT|

一般取β=0.25\beta = 0.25

重传时间RTORTO就取:

RTO=RTTS+4×RTTDRTO = RTT_S + 4\times RTT_D

但是考虑到一种特殊的报文: 重传报文。如果一报文的确认并未收到,于是重发。重发后收到确认信息。

该确认信息如果是重传报文的确认却被认为是最初报文的确认,则会导致该RTTRTT样本偏大,导致重传时间也偏大;但如果该确认信息是最初报文的确认却被认为是重传确认,则会导致该RTTRTT样本偏小,算出的重传时间RTORTO也偏大了。判断该确认很麻烦,导致计算也很麻烦。

于是改进后的算法中对于重传报文的确认是这样使用的:

  1. 重传报文的RTTRTT样本一律不采用

但是又出现了一种情况: 网络状况突然变得很不好,所有报文都要重传!这又导致重传时间不会更新,所以整个网络一直处于重传中。。。

再次更新算法:

于是改进后的算法中对于重传报文的确认变成这样使用:

  1. 重传报文的RTTRTT​样本一律不采用
  2. 每次重传以后,取RTO()=γRTO()RTO_{(新)} = \gamma \cdot RTO_{(旧)}一般取γ=2\gamma = 2

实践证明,这样就合理了。。。

3.3.2 TCPTCP​的发送/接收窗口#

3.3.2.1 发送窗口#

发送窗口指的是: 在没有接收到确认的情况下,能够发送出去的数据的字节数

任何已经发送但是没有收到确认信息的数据,都要先放在发送方的发送缓存里

接收方BB的接收窗口一定比发送方AA的发送窗口要小

发送窗口有3个指针:

P1P_1: 发送窗口后沿[可以发送的第一个字节可以发送的第一个字节]

P2P_2: 第一个还没有发送的字节

P3P_3: 发送窗口前沿[不能发送的第一个字节]

P2P1P_2 - P_1: 已经发送但还没有被接收的字节数

P3P1P_3 - P_1: 发送窗口大小

P3P2P_3 - P_2: 还可以发送但是尚未发送的字节数

发送窗口的后沿和发送缓存重合。(已确认的立刻删除)

发送窗口保存的是:

  1. 要发送但是还没发送的数据
  2. 已经发送但是没有收到确认的数据

3.3.2.2 接收窗口#

接收窗口保存的是:

  1. 已经连续确认但是没有被读应用进程取走的数据
  2. 未按序到达确认的数据

接收方BB的每个确认值都是当前没收到的第一个字节的序号

接收确认一般使用累积确认,这样可以减小网络传播开销。选择合适的时间把确认信息传递给对方,比如累积一定的确认、在发送自己的数据时捎带上确认信息。

3.3.3 TCPTCP的流量控制#

TCPTCP​​​的流量控制也是用接收窗口/发送窗口来控制。

CAUTION

当接收方告诉发送方发送窗口wnd=0wnd = 0时就不允许发送方在发送数据。但是万一要发送的数据仍然没有发送完毕,发送方就会一直以为发送窗口仍然是0,哪怕接收方已经处理好了缓存。

一个解决办法是: 设置一个0窗口等待计时器,当计时器计时结束后发送一个0窗口探测报文,接收方在对该探测报文的确认中给出自己的窗口值。非0则可以传送数据,为0则重置等待计数器!

:::tip thinking

由于TCPTCP报头至少是2020字节,IPIP数据报头又是2020字节,如果发送一个字节的数据,并且要求确认,线路上至少要传递1+20+201 + 20 +20 + 20+20=8120 +20 = 81[假设确认消息不需要发送数据部分]。如果要求接收方也要发送一个字节的确认数据,且不采用捎带确认和累积确认,则这一个字节的数据也需要共8181个字节,只传送一个字节则需要一共162162字节,44​个数据报。

但是如果使用捎带确认信息,则发送确认数据时可以把第一个数据报的确认也捎带,一共只需要33个数据报,41+41+40=12241+41+40 = 122字节。

可见捎带确认和累积确认对减轻网络阻塞和提高利用率都很重要。

另外TCPTCP报文数据段也不宜太短,最好是累积一些数据以后再一起发送出去。

:::

发送方一般采用NagleNagle算法:

  1. 只有当前一个发送出去的数据报得到确认以后,再把缓存中的所有数据装成一个数据报发送出去第一次只发送最初缓存中的第一个字节。
  2. 当数据已经达到窗口大小的一半或者最大长度时,就立刻发送一个数据报。
CAUTION

考虑一种情况:网络速度很快但是接收方处理非常慢——糊涂窗口综合征

极端情况下每一次发送/确认(一个RTTRTT的时间),接收方只能处理11个字节,确认信息中会告诉发送方只能有11个字节的发送窗口,发送方就会每次只发送一个字节,造成传输效率不高。

有效的解决办法有:

  1. 先不发送数据,等待接收方处理一会数据[计时器]。
  2. 等接收方的缓存有至少一半空闲时才继续发送数据。
网络原理: 运输层
http://blog.fragments.work/posts/computernetwork/ch5/
作者
Lixin WANG
发布于
2024-05-30
许可协议
CC BY-NC-SA 4.0