运输层两个重要协议

  • UDP: User Datagram Protocol 用户数据报协议
  • TCP: Transmission Control Protocol 传输控制协议

运输层用一个16位端口号来标志一个端口,可表示 65535个不同端口号,分为下面两大类:

  • 服务端使用的端口号:
    • 系统端口号或熟知端口号,数值为0~1023,IANA把这些端口号指派给了TCP/IP最重要的一些应用程序。
      计算机网络知识整理 - 运输层
    • 登记端口号,数值为1024~49151,为没有熟知端口号的应用程序使用,使用这些端口号必须在IANA按照规定的手续登记,以防重复。
  • 客户端使用的端口号, 又叫做短暂端口号,数值为49152~65535,这类端口号仅在客户进程运行时才动态选择。

UDP

1,主要特点

  • 无连接:减少了开销和发送数据之前的时延
  • 尽最大努力交付:不保证可靠交付,因此不需要维持复杂的连接状态
  • 面向报文:对应用层交下来的报文,不合并也不拆分,保留这些报文的边界,添加首部后就交付IP层,因此应用程序必须选择合适大小的报文
  • 没有拥塞控制:网络出现拥塞不会使源主机的发送速率降低。
  • 支持1:1, 1:N, N:1, N:N的交互通信
  • 首部开销少,只有8个字节。

不使用 拥塞控制 功能的 UDP 有可能会引起网络 更严重的拥塞问题

2,报文结构

UDP有两个字段,数据字段和首部字段,首部字段只有8个字节,由四个字段组成。
计算机网络知识整理 - 运输层

  • 源端口:需要对方回信时选用,不需要时可全为0
  • 目的端口:在重点交付报文时必须使用
  • 长度: UDP用户数据报长度,最小值为8(仅有首部)
  • 校验和: 检测UDP用户数据报在传输中是否有错,有错就丢弃。

伪首部:12个字节,不是UDP用户数据的真正首部,既不 向下传送 也 不向上递交,仅仅是为了计算校验和。

3,校验和计算方式

发送方

  • 先把全0 放入校验和字段
  • UDP数据报的数据部分如果不是偶数个字节,则填入一个全0字节(此字节不发送)
  • 按二进制反码计算出伪首部及UDP用户数据报的和,将此和的二进制反码写入校验和字段
  • 发送UDP用户数据报
    接收方
  • 收到的UDP用户数据报连同伪首部(以及可能的填充全0字段),按二进制反码求和
  • 若无差错,其结果应为全1,否则表明有差错。
    计算机网络知识整理 - 运输层

TCP

1,主要特点

  • 面向连接的运输协议。即 建立连接 --> 通信 --> 释放连接
  • 每一条TCP连接只能是点对点的
  • TCP提供可靠交付。即无差错,不丢失,不重复且按序到达
  • 提供全双工通信。允许通信双方的应用进程在任何时候都可以发送数据,TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据
  • 面向字节流。虽然应用程序和TCP交互式一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。

套接字

  • TCP连接的端点叫做套接字(socket) 或 插口, 套接字 socket = (IP: port)
  • 每一条TCP连接唯一的被通信两端的两个端点(即两个套接字)所确定:
    TCP连接:= {socket1, socket2} = {(IP1: port1), (IP2: port2)}

2,报文结构

TCP报文首部格式,前20个字节是固定的,后面有4n字节是根据需要而增加的选项,(n是整数)
计算机网络知识整理 - 运输层

  • 源端口 和 目的端口: 各占 2个字节
  • 序号: 4字节,范围[0, 2^32 - 1],即4 294 967 296个序号,需要增加到2^32 – 1后,下一个需要就又回到0,序号值 指的是本报文段 所发送的数据的第一个字节的序号。eg: 一段报文的序号字段值是301,携带的数据有100字节,表明本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400,下一个报文段的数据序号应当从401开始。
  • 确认号: 4字节。期望收到对方下一个报文段的第一个数据字节的序号。eg: A发送一个报文段,序号字段值是301,携带的数据有100字节,B正确收到了A发送的到序号400为止的数据,因此B期望收到A的下一个数据序号是401,于是B在发送给A的确认报文段中把确认号置为401。
    计算机网络知识整理 - 运输层
  • 数据偏移: 占4位,TCP报文段数据部分起始处 到 TCP报文段的起始处长度,即TCP报文段的首部长度。4位二进制对应十进制数字15,即数据偏移最大值是60字节,也就是TCP首部最大长度(即选项长度不能超过40字节)
  • 保留: 占6位,目前置为0
  • 6个控制位,用来说明本报文段性质。
    • 紧急URG:URG=1表明紧急指针字段有效。发送应用进程告诉发送方的TCP有紧急数据要传送,发送方TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。所以需要配合首部的紧急指针字段使用。
    • 确认ACK:仅当ACK=1时确认字段有效,其他无效。TCP规定,连接建立后所有传送的报文段都必须把ACK置1。
    • 推送PSH:发送方TCP把PSH置1,并立即创建一个报文段发送出去,接收方TCP收到PSH=1的报文段,就尽快的(即“推送”向前)交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。
    • 复位RST:也可称为重建位或重置位,RST=1表明TCP连接中出现严重差错,必须释放连接,然后再重新建立运输连接,还可用来拒绝一个非法的报文段或拒绝打开一个连接。
    • 同步SYN:连接建立时用来同步序号。SYN=1&ACK=0,表明这是一个连接请求报文段。若对方同意建立连接,则响应报文段中使SYN=1&ACK=1。
    • 终止FIN:用来释放一个连接。FIN=1表示此报文段的发送方的数据发送完毕并要求释放连接。
  • 窗口: 占2字节。窗口值是[0, 2^16 - 1]之间整数。指发送本报文段一方(即自己)的接收窗口(并非自己的发送窗口),含义:接收方目前允许发送方发送的数据量(字节),窗口值作为接收方让发送方 设置其发送窗口的依据。窗口值 明确指出现在允许对方发送的数据量,经常在动态变化。例如:接收方发送了一个报文段,确认号是701,窗口字段是1000,即告诉对方:从701号起,我的接受缓存空间还可再接收1000个字节数据。
  • 校验和: 占2字节。和UDP教研方式一样,1,需要加上12字节伪首部,伪首部第4个字段中的17改为6(TCP的协议号是6)第5字段中UDP长度改为TCP长度。
  • 紧急指针: 占2字节。仅在URG=1时有意义。本报文段中紧急数据的字节数。值得注意的是:即使窗口为0时也可以发送紧急数据。
  • 选项: 长度可变,最长40字节。

MSS(Maximum Segment Size):最大报文段长度:= TCP报文段长度 – TCP首部长度。

窗口扩大选项: 占3字节。其中有一个字节代表移位值S,S范围[0, 14],若设置,
新的窗口值=TCP首部中的窗口位数 + S,若都为最大值,相当于窗口最大值增大到
2^(16 + 14) – 1 = 2^30 – 1。

时间戳选项: 占10字节,最主要字段是:时间戳值字段(4字节)和 时间戳回送回答字段(4字节),时间戳选项有两个功能:

  • 用来计算往返时间RTT,接收方把发送方设置的时间戳值返回去,发送方再收到确认报文后,即可算出RTT
  • 处理TCP序号超过2^32情况,又称为防止序号绕回PAWS(Protect Against Wrapped Sequence numbers)。当序号被重复使用时(假如用2.5Gbit/s速率发送报文段,不到14s序号就会用完重复),用来区分新旧报文。

3,可靠传输

  • 以字节为单位的滑动窗口
    假设A的发送窗口和B的接收窗口:
    • A的发送窗口一定不能超过B的接收窗口数值。
    • 发送窗口:在没有收到B的确认情况下,A可以连续把窗口内的数据都发送出去。凡是已经发送出去的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。
    • 发送窗口位置由 窗口前沿 和 窗口后沿 位置共同决定。窗口后沿 后面的 数据表示 已经发送 且 已收到确认,不需要再保留。窗口前沿 前面的 数据表示 不允许发送的,因为接收方 还没有 临时存放的缓存空间 来 保留这部分数据。
    • 假设A发送31-40的数据,B收到了序号为32, 33的数据,因为序号31数据没有收到,所以B只能对按序收到的数据中(前面30个按序收到了)最高序号给出确认,所以B发送的确认报文段中的确认号还是31,(即期望收到的序号),而并非32或33.
  • 超时重传时间选择
    • RTT:报文往返时间
    • RTTs:加权平均往返时间,又称为平滑往返时间。
    • 第一次测量到RTT样本时,RTTs值 = 测量到的RTT样本值。之后每测量到一个新的RTT样本,就按照如下公式计算一次RTTs:
      计算机网络知识整理 - 运输层
    • α值推荐为1/8,即0.125
      计算机网络知识整理 - 运输层
  • 选择确认SACK
    只传送缺少的数据,而不需要重传已经正确到达接收方的数据。
    问题点, 首部选项字段 最多 40字节,除过 一个字段 用来指明 SACK选项,一个字段 指明 这个选项 需要占用的 字节数,剩余38字节。收到的前后不连续的字节块有两个边界:左边界和右边界,即左序号和有序号,每个序号32位,占4个字节,即返回确认时报告接收到的不连续的一个字节块需要8个字节,因此选项中最多只能指明4个字节块边界信息。
    其次,SACK文档并没有指明发送方应当怎样响应SACK,因此大多数的实现还是重传所有未被确认的数据块。

问题

  • 发送出一个报文段,重传时间到后,还未收到确认,于是重传该报文段,一段时间后收到了确认报文段,如何判断 此 确认报文段 是对 先发送的报文段的确认 还是 对重传的报文段确认
    判断有误导致计算的RTO时间不准确

解决方案:报文段每重传一次,就把超时重传时间RTO增大一些,一般可设置为旧重传时间的2倍,当不再发生报文段的重传时,再根据上面公式计算超时重传时间。

4,流量控制

  • 流量控制:flow control,点到点通信量的控制,是端到端问题,抑制发送端发送数据的速率,以便使接收方来得及接收。
  • 利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制。

问题

  • B向A发送了零窗口报文段后不久,B接收缓存有了些空间,于是向A发送了非零窗口报文段,但此报文段可能在传输中丢失了导致A未收到通知而一直等待,B以为A收到了通知而一直等待A发送数据,形成死锁

解决方案:TCP为每个连接设有一个持续计数器(persistence timer),只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器,计数器时间到期,就发送一个零窗口的探测报文段(仅携带1字节数据),而对方就在确认这个探测报文段时给出现在的窗口值。如果窗口值还是为0,那收到这个报文段的一方再重新设置持续计数器。

TCP规定,即使设置为零窗口,也必须接收以下几种报文段:零窗口探测报文段,确认报文段和携带紧急数据的报文段。

5,拥塞控制

  • 拥塞控制:防止过多的数据注入到网络中,导致网络中的路由器或链路过载。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。
  • TCP进行拥塞控制的算法有四种:
    • 慢开始(slow-start)
    • 拥塞避免(congestion avoidance)
    • 快重传(fast retransmit)
    • 快恢复(fast recovery)

(目前先不考虑接收方,会面会提出)

慢开始和拥塞避免

  • 发送方维持一个拥塞窗口cwnd(congestion window),拥塞窗口大小取决于 网络的拥塞程度 且 动态变化,发送方让自己的发送窗口等于拥塞窗口。判断网络拥塞的依据:是否出现了超时

  • 慢开始:由小到大逐渐增大拥塞窗口值。
    SMSS: Sender Maximum Segment Size,发送发的最大报文段。
    旧规定:刚开始发送报文段时,初始拥塞窗口cwnd设置为1至2个SMSS数值

  • 新RFC5681把初始拥塞窗口cwnd设置为不超过2至4个SMSS数值:

    • 若 SMSS > 2190字节:
      初始拥塞窗口cwnd = 2 * SMSS字节 且 <= 2个报文段。
    • 若 SMSS > 1095字节 并且 SMSS <= 2190字节:
      初始拥塞窗口cwnd = 3 SMSS字节 且 <= 3个报文段。
    • 若 SMSS <= 1095字节:
      初始拥塞窗口cwnd = 4 * SMSS字节 且 <= 4个报文段。
    • 之后,每收到一个对新的报文段确认后,就把拥塞窗口增加最多一个SMSS数值:
      拥塞窗口cwnd每次增加的增加量 = min(N, SMSS), N即刚收到的确认报文段确认的字节数。
  • 传输轮次:transmission round,一个传输轮次所经历的时间 就是 往返时间RTT,RTT并非恒定数值。传输轮次更加强调的是:把拥塞窗口cwnd所允许发送的报文段都连续发送出去,并收到对已发送的最后一个字节的确认。假如:
    cwnd大小是4个报文段,那么往返RTT就是发送方连续发送4个报文段,并收到这4个报文段的确定,所经历的时间。
    每经过一个传输轮次,拥塞窗口cwnd就近似于加倍

  • 为防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量:

    • 当 cwnd < ssthresh 时,使用慢开始算法。
    • 当 cwnd > ssthresh 时,停止使用慢开始算法,改用拥塞避免算法。
    • 当 cwnd = ssthresh 时,使用慢开始算法 或 拥塞避免算法。
  • 拥塞避免:每收到一个新的确认,拥塞窗口cwnd增加(MSS * MSS / cwnd)。每经过一个往返时间RTT(也就是一个传输轮次),也就是收到n个确认报文段,拥塞窗口就近似增加一个MSS(理想情况下,即每次发送的报文段长度都=MSS,且cwnd = n * MSS,即
    MSS * MSS/(n * MSS) * n = MSS * (n * MSS) / (n * MSS) = MSS)。

因此,拥塞避免阶段就有 “加法增大” AI(Additive Increase)特点,即在拥塞避免阶段,拥塞窗口cwnd按线性规律缓慢增大,比慢开始算法的拥塞窗口cwnd窗口增长速率慢很多。
举例说明(便于理解,途中窗口单位不用字节,使用报文段个数):
计算机网络知识整理 - 运输层

  • 初始阶段:拥塞窗口cwnd=1,慢开始门限ssthresh=16
  • 慢开始阶段 0-4:第0轮次发送1个报文段,收到1个确认,cwnd=1+1,第1轮次发送2个报文段,收到2个确认,cwnd=2+2,第2个轮次发送4个报文段,收到4个确认,cwnd=4+4,以此类推,第4轮cwnd=ssthresh=16,启用拥塞避免算法。
  • 拥塞避免阶段 4-12:每经过一个轮次,cwnd=cwnd+1
  • 超时:此时是第12个传输轮次,cwnd=24,调整门限ssthresh=cwnd/2=12,同时设置cwnd=1,进入慢开始阶段。
  • 快重传:之后到第21个传输轮次,cwnd=16时,发送方连续收到3个对同一个报文段的重复确认(3-ACK),表明目前非网络拥堵,需进行快重传,避免超时判为网络拥堵导致再次进入慢开始。
  • 快恢复:发送方知道目前只是丢失个别报文段,而非网络拥堵,所以不启动慢开始,而是执行快恢复,此时调整cwnd=ssthresh=cwnd/2=8,并开始执行拥塞避免算法。

快重传
计算机网络知识整理 - 运输层
TCP拥塞控制流程图
计算机网络知识整理 - 运输层

  • 接收方窗口又称为通知窗口(advertised window)
  • 接收方根据自己的接收能力设定了接收方窗口rwnd,并把这个窗口值写入TCP首部中的窗口字段传送给发送方。
  • 所以:发送方的窗口 一定不能 超过对方给出的接收方窗口值rwnd。即:
    发送方窗口上限值 = min[接收方窗口rwnd, 拥塞窗口cwnd]
    当rwnd < cwnd时,是接收方的接受能力限制发送方窗口最大值。
    当cwnd < rwnd时,是网络的拥塞程度限制发送方窗口最大值。

6,三次握手

计算机网络知识整理 - 运输层

  • A 向 B发出连接请求报文段,首部中同步位SYN=1,同时选择一个初始序号seq=x。A进入SYN-SENT(同步已发送)状态。
  • B收到连接请求后,如同意建立连接,则向A发送确认。确认报文段中SYN=1且ACK=1,确认号ack=x+1,同时为自己选择一个初始序号seq=y。B进入SYN-RCVD(同步收到)状态。
  • A收到B的确认后,再次向B给出确认。确认报文段ACK=1,确认号ack=y+1,自己的序号seq=x+1。TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。
  • B收到A的确认后,也进入ESTABLISHED(已建立连接)状态。

注意

  • SYN报文段(即SYN=1的报文段)不能携带数据,带药消耗掉一个序号。
  • ACK报文段可以携带数据,如果不携带,则不消耗序号,这种情况下,下一个数据报文段序号仍是seq=x+1.

四次报文握手则是 把 B 发送给A的确认报文段拆成两个报文段:先发送一个确认报文段(ACK=1, ack=x+1),再发送一个同步报文段(SYN=1, seq=y),效果一样

问题:A最后为什么还要发送一次确认呢
如果不确认,会出现一种情况:A第一次发出的连接请求没有丢失,只是延误了到连接释放后某个时间点到达B,B误以为A有发出了一次新的连接请求,于是向A发出确认报文,同意连接,导致B以为新的运输连接已经建立,并一直等待A发送数据,资源浪费。

7,四次挥手

计算机网络知识整理 - 运输层

  • A应用向其TCP发出连接释放报文段,并停止再发送数据,主动断开连接,A把连接释放报文段首部终止控制位FIN置为1,序号seq=u(前面已传送过的数据的最后一个字节的序号+1),此时A进入FIN-WAIT-1(终止等待1)状态。
  • B收到连接释放报文段后发出确认,ack=u+1,序号seq=v,然后B进入CLOSE-WAIT状态,并通知应用进程,因而A到B方向的连接就释放了,此时TCP连接处于半关闭(half-close)状态,即A已经没有数据要发送,但B如果有数据发送,A仍要接收,也就是B到A的连接还未关闭。
  • A收到确认后, 进入FIN-WAIT-2(终止等待2)状态,等待B发出连接释放报文段。
  • 若B已经没有要向A发送的数据,应用进程就通知TCP释放连接,此时B发出连接释放报文段FIN=1,假定B的序号为w(半关闭状态B可能又发送了一些数据),B还必须重复上次已发送过的确认号ack=u+1,这时B就进入LAST-ACK(最后确认)状态。
  • A收到B的连接释放报文段后,必须对此发出确认。确认报文段中,ACK=1,确认号ack=w+1,自己的序号seq=u+1,然后进入到TIME-WAIT(时间等待)状态,此时,TCP连接还没有释放掉。
  • 经过时间等待计时器(TIME-WAIT timer)设置的时间2MSL后,A才进入到CLOSE状态。时间MSL叫做最长报文段寿命(Maximux Segment Lifetime),RFC739建议设为2分钟,也允许不同的实现可根据具体情况使用不同的MSL值。

问题:为什么A在TIME-WAIT必须等待2MSL时间呢?

  • 保证A发送的最后一个ACK报文能够到达B。如果B没有收到,会超时重传FIN+ACK报文段,A就能够在2MSL时间内收到这个报文段,然后A重传一次确认并重新启动2MSL计时器。确保B能按照正常步骤进入CLOSED状态。
  • MSL 是TCP 对TCP Segment 生存时间的限制。A在发送完最后一个ACK报文段后,经过时间2MSL,可以确保本连接持续时间内所有产生的报文段都从网络中消失,这样就可以使下一个新的连接中不会出现这种旧的报文段。

保活计时器

  • 除时间等待计时器外,TCP还设有一个保活计时器(keepalive timer):
    服务器每收到一次客户的数据,会重新设置保活计时器,通常是两小时,若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后每隔75秒发送一次,若连续发送10个探测报文段后仍无客户的响应,则认为客户端出了故障,关闭连接。

8,有限状态机

  • TCP连接建立和释放:
    客户端对应的是 粗实线箭头 所指状态变迁
    服务端对应的是 粗虚线箭头 所指状态变迁
    计算机网络知识整理 - 运输层

相关文章:

  • 2022-12-23
  • 2021-10-26
  • 2021-08-02
  • 2021-10-14
  • 2021-07-07
  • 2021-08-11
猜你喜欢
  • 2021-04-06
  • 2021-03-31
  • 2021-12-06
  • 2021-10-11
  • 2021-07-09
  • 2021-10-14
  • 2021-12-09
相关资源
相似解决方案