运输层
本节重点
- 运输层为相互交互的通信的应用进程提供逻辑通信
- 端口和套接字的意义
- 无连接的UDP含义
- 面向连接的TCP特点
- 在不可靠的网络上实现可靠传输的工作原理,停止等待协议和ARQ协议
注 运输层最近又添加了第三种协议 ,STCP(Stream Cntrol Transmission Protocol) [建议标准] 它具有TCP和UDP的协议的共同优点
运输层协议概述
进程间的通信
运输层向他上面的应用层提供通信。
当网络边缘的主机使用网络的核心功能进行端对端通信时,只有主机的协议栈才有运输层,核心部分一般都只有三层结构 。
通信的真正端点时主机和主机之间的进程
逻辑通信 : 从应用层来看,只要把应用层报文交给下面的运输层,运输层就可以把报文传输给对方的物理层。
运输层还要对收到的报文进行检错。前面的网络层, 只是对应的数据报的首部的检测。网络层为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信
运输层的两个协议
TCP/IP运输层的两个协议都是互联网的正式标准即:
- 用户数据协议UDP(User Datagram Protocol)
- 传输控制协议TCP(Transmission Control Protocol)
按照OSI的术语: 两个对等的运输实体在通信传输时的数据单元叫做运输数据控制单元
TPDU(Transport Protocol Data Unit 。 在TCP和UDP分别称之为TCP报文段(segment
和UDP用户数据报
使用UDP和TCP 协议的各种应用和应用栈协议
TCP和UDP使用一个16位的端口号来标示一个端口号。端口号只有本地意义,就是为了表示计算机应用层中的个进程在 和运输层在交互时的接口。 16位的端口号允许65535个不同的端口号。
- 服务器使用的端口号 ,或者比较熟知的端口号(Well-known port number)或者系统端口号 :
常用的熟知的端口号
另一类叫做登记端口号,数值为1024-49151 。 这类端口时为没有熟知端口号的应用程序的使用, 使用这类端口号必须在IANA
按照规定的手续登记,以防止重复
- 客户端使用的端口号 熟知为49152-65535 短暂端口号
用户数据包协议UDP
UDP只在IP的数据报之上添加了很少的功能。就是复用和分用以及 差错检错的功能 :
- 特点:
- UDP是无连接的
- 尽最大努力交互
- UDP时面向报文的 对应用层传过来的数据添加UDP首部后就直接的交付给下层IP协议
- UDP没有阻塞控制
- UDP支持一对一,一对多和多对多的相互通信
- UDP的首部开销少
UDP的首部格式
共8个字节
- 源端口 需要对对方回信时选用 。不需要为可以全为0
当运输层收到UDP数据报,就是根据首部中的目标地址,把UDP数据报通过相应的端口,上交给最后的终点---应用进程
图中伪首部,主要时为了计算检验和,临时添加到UDP用户数据报之前。 - 数据检验的方式:
首部和数据部分一起检验
- 用0填充首部检验和字段
- 取偶数个字节进行加法运算 (奇数,补零 ,运算,实际的数据中没有)
- 结果求反码放入到首部检验和字段
- 接受方:
将伪首部和UDP数据报进行求和,结果全为 1 ,无错,否则丢弃。
传输层控制协议TCP
TCP协议的主要特点 :
- TCP时面向链接的运输层协议
- 每一条TCP链接只能有两个端点。TCP链接只能时点对点
- TCP提供可靠交付服务
- TCP提供双全共服务
- 面向字节流
TCP把链接作为最基本的抽象,TCP的许多特性都与TCP是面向链接的这个基本属性有关。 TCP的两个端点叫套接字
或接口 。
[RPC 793]定义: 端口号拼接到(Connection with)IP地址即构成了套机字。
套接字socket = (IP地址:端口号)
每条TCP链接唯一地被通讯两个端点(即套接字) 所确定。即:
TCP链接::={socket1,socket2}= {(IP,端口号),(IP2,端口号)}
TCP报文段的首部格式
其中个别字段解释:
序号: 在TCP链接中传输的字节流中的每个字节都是按顺序编号的。字节的起始信号在建立链接时候确认。
确认号 : 期望收到下一个报文段的第一个字节的序列
数据偏移 : 数据离起始TCP报文段起始处有多远
紧急URG(URgent) : 优先处理 ,配合紧急指针使用
推送PSH(PuSH):不缓冲立即发送
复位RST(ReSeT) : 表明TCP链接出现严重的差错,必须释放连接,然后重新建立 。
SYN标志,表示请求建立一个连接。我们称携带SYN标志的TCP报文段为同步报文段。
FIN标志,表示通知对方本端要关闭连接了。我们称携带FIN标志的TCP报文段为结束报文段。
16位窗口大小(window size):是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
16位校验和(TCP check sum):由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏。注意,这个校验不仅包括TCP头部,也包括数据部分。这也是TCP可靠传输的一个重要保障。
16位紧急指针(urgent pointer):是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP的紧急指针是发送端向接收端发送紧急数据的方法
TCP头部选项:TCP头部的最后一个选项字段(options)是可变长的可选信息。这部分最多包含40字节,因为TCP头部最长是60字节(其中还包含前面讨论的20字节的固定部分
随着发展TCP报文格式也发生这变化,使得传输更加的高效,可靠。
例如: 窗口扩大 选择确认
可靠传输的原理
- 理想的传输条件具备的两个特点:
- 传输信道不产生差错
- 不管发送方以 多块的速度发送数据,接受方总是来得及处理接受到的消息
停止等待协议
就是每发送一个分组就停止发送,等待对方确认。收到确认后在发送下一个分组。
- 每次发送完都需要保留一个暂时的副本。只有收到确认分组才能清除
- 需要对分组和分组确认编号
- 设定超时计算器
三种情况: - 正常,无差错
- 出现差错 ,继续重发
- 确认丢失和确认迟到 (会发送重复的包忽略)
上述协议也可以称为自动重传ARQ(Automatic Repeat reQuest)。意思时: 重传的请求时自动进行的,接受方不需要请求发送方重传某个出错请求 - 改进的思路: 使用流水线一次发送多个分组,在请求确认。
连续的ARQ协议
位于滑动窗口内的5个分组都可以连续的发送出去,而不需等待确认。 发送每收到一个确认就把窗口向前滑动一个分组的单位。接受方不必对收到的数据逐个发送确认,而是在收到几个分组红颜,对按序到达的最后一个分组发送确认。 出现差错时,使用Go-back-N(回退N。
TCP实现可靠传输的特点
同样TCP使用的滑动窗口实现的,但是如果存在确认丢失,那么也是采用超时重传的方法来确定。 但是超时时间设置也是比较的复杂 ,采用自适应算法
超时重传时间的选择
TCP采用的是一种自适应算法,它是记录一个报文发出的时间,以及收到相应的确认时间 。这两时间之差就是报文的往返时间RTT
TCP保留了一个加权平均往返时间RTTs
,这又称为平滑的往返时间。 当第一次测量到RTT样本时,RTTs值就为RTT样本的值,以后没采测到一次,就按照下面的公式计算一次:
新的RTTs=(1-α)× (旧的RTTs) + α× (新的RTT样本)
标准建议设置为:0.125
- 上面时RTT的计算方法,下面给出超时重传时间RTO(Retransminssion Time-OUT) 应略大于上面得出的加权平均时间RTTs。
标准建议 :
RTO = RTTs + 4* RTT<sub>D</sub>
RTTD 建议的计算值: 当一次计算时,RTT 的取值为RTT样本值的一半 ,以后的计算方法
新的RTT<sub>D</sub> = (1-β)×(旧的RTT<sub>D</sub>)+ β×ABS(RTTs-新的RTT样本)
β的推荐值0.25
但时这种算法有缺陷。重传后,收到前面的一个确认报文,无法确定时那个分组的RTT。
若是前一个,则RTTS和增大, 若是后一个减少。
- 解决上述问题:
Karn
提出思路: 发送重传时不计算. 映入了一个新的问题: 假设重传时延变得非常大,不计算重传,就无法重新计算RTO的时间 - 在为了解决上述的问题,将RTO的时间确定的大一点,重传的时间直接计算为原来的2倍。
选择确认 SACK
若收到的报文无差错 , 只是序号序号未按照序号,中间的缺少一些
数据,不必重传,只需要传输缺少的数据
TCP流量控制
所谓的流量控制(flow contro)就是让发送方发送速率不要太快,要让接受方来的及接受
假设问题:B发送rwnd= 0,A接受到后不在发送数据,但是一段时间后,B的rwnd = 400,但是在发送rwnd=400的报文段丢失了。那么A就一直等待B发送︿( ̄︶ ̄)︿非零窗口的报文段,B也在等待A的数据报陷入相互死锁的问题 。
解决办法:使用一个持续的计时器,时间一到就发送一个零窗口的探测报文段。
- TCP的传输效率
当应用进程吧数据传送到TCP后,TCP就缓冲起来了,剩下的发送任务就由TCP来来控制了 。TCP提供了不同的机制来控制TCP报文段的发送时机 - TCP 维持一个变量MSS 。只有缓冲到达MSS,就启动发送
- 发送方应用指明了TCP支持的push操作,直接发送
- 维持一个计时器,时间到就发送
在TCP实现中使用的是Nagle算法
: 先发送一个字节,然后等待确认,然后后面到达的数据缓冲,再把缓冲中的所有数据组装成一个数据段在发送出去。
只有接受到前一个数据段的确认在发送下一个。 - 糊涂窗口综合征(silly window syndrome): 接受方的缓冲处理太慢,而发送方接受到确认后,继续发送,部分数据丢失,同样是的效率减低 。解决方法:① 接收方等待一段时间后 ② 等待接收缓冲区有一半空闲的空间。 在发送确认数据段,并通知当前窗口的大小。
TCP的拥塞控制
网络中某一资源超过了网络性能就会变坏。
TCP进行拥塞控制的算法一共有四种。
慢开始 拥塞避免 快重传 快恢复
- 慢开始:开始cwnd为1 , 通过轮次(上一轮的数据报都发送完)的方法,利用乘法来扩大拥塞窗口 ,且不能超过1到2个发送方的SMSS的最大报文段 (新的标准3-4个大小)
SMSS 在SYN中协商,默认时536字节。
实际中,发送方只要接受到对新报文的确认就立即对cwnd窗口值加1,不需要等待上一轮次全部传送完毕。
为了防止cwnd太大,需要设置慢开始门限。 当cwnd>门限值,使用拥塞避免算法 - 拥塞避免 就是加法运算,每次对cwnd增1,当出现超时,设置门限值为cwnd/2 ,同时设置 cwnd为1,开始慢算法。
- 快算法解决报文丢失,再次引起慢算法的问题。若发生丢失报文段,则接受方连续的发送前一个数据段的 重复确认3次,累计4次 ,发送方就知道了的确没有收到丢失的报文,因而当立即重传,而不是网络拥堵。 启动快速恢复算法。 调整发送方的门限值为8,同时设置cwnd = 8。
TCP的传输链接管理
TCP时面向链接的协议,运输连接是用来传输TCP报文的。TCP运输连接的建立和选择时面向连接的通信中必不可少的。 因此运输连接必有三个阶段,即: 连接建立,数据传送,连接释放。 运输连接的管理就是使得运输连接的建立和释放都能正常的进行。
- TCP连接建立解决的三大问题:
- TCP 的每一方都要能够感知对方的存在
- 要允许双方协议一些参数
- 能够对运输实体资源(缓存的大小,连接表中的项目)进行分配。
TCP 连接建立采用的时客服服务器模式,主动发起建立请求的应用进程叫做客户,被动等待建立连接的时应用进程叫做服务器
- TCP的连接建立
TCP建立连接的过程叫做握手(三报文握手), 握手需要在客户和服务器之间交换三个TCP报文段
详细过程:
- 假定A运行的时TCP客户端程序,B运行的时服务器段的程序。最初两端的TCP进程都处于CLOSED(关闭状态).此时A主动的打开连接,B被动打开连接
B进程TCP服务器先创立传输控制块TCB,准备接受客户端进程的请求连接。然后服务器处于 LISTEN(收听)状态,等待客户端的连接请求。 - A的TCP进程首先创建传输控制模块TCB, 然后打算建立TCP连接,向B发送连接请求报文,这是首部的同步位为1,同时选择一个初始化序列SYN=1 ,同时选择一个初始化序号seq=x (TCP规定SYN为1的报文段不能携带数据)但是要消耗一个序号。
TCP客户端进程进入发SYN-SENT(同步已发送)阶段。 - B接受带请求报文后,如果同意建立,则向A发送确认。在确认报文段中应把SYN位和ACK为置一。确认号是ack=x+1。同时也为自己选择一个初始化序号seq=y. 同样这个报文段也不能携带数据,但是消耗一个序号。 这是TCP 服务器进程进入到SYN-RCVD(同步收到)状态。
- TCP客户端收到B的请求后,还有给B发出确认请求。确认报文段的ACK置1,确认号ack=y+1,而自己的seq=x+1, 因为SNY=0,所以序号不用增加就是ack=y+1,而seq仍然为x+1.
- B收到A的请求后,也进入到ESTABLISTEND(已建立)状态
为什么最后一次还要发送一次确认? 主要时为了防止已经失效的连接请求报文段突然又穿送到了B,产生错误。失效的连接
A发出连接请求,但因为请求连接报文滞留在网络。以至于A的连接释放后才到达了B,B认为是一个新的请求连接,发送确认报文段(如果两次握手,那么已经建立连接,A不予回应)浪费资源。
TCP的连接释放。
TCP的连接关闭也是比较的复杂的,需要四次握手。
- 在数据传输结束后,通信的双发都可释放连接。现在A和B都处于ESTABLESHED状态。A的应用进程先向其TCP发出连接释放报文段,并停止发送数据,主动关闭TCP连接。A连接释放报文段的首部终止控制位置1,其序号为 seq = u ,u为前面已经传送的过的数据的最后一个序号加1。这是A进入到 FIN-WAIT-1(停止等待1)状态。 等待B的确认。
TCP规定FIN报文段即使不携带数据,它也消耗一个序号
- B收到连接释放报文段后立即发送确认。确认号时是ack=u+1; 而这个报文段自己的序列号时V。等于B前面已经传送的数据的最后一个字节加1。然后B进入到CLOSE-WAIT
(关闭等待)TCP的服务端进程这时通知高层应用程序进程,因而从A到B的这个连接就是释放了,这是TCP连接处于半关闭状态, 即A已经没有要发送的数据了。但是B若发送数据A仍然接受 。B到A的连接还没有关闭,将会保持一段的时间。 - A收到的B的确认,就进入到FIN-WAIT2(停止等待2) 状态。 等待B发出的连接释放报文段
- 若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的释放连接报文必须时FIN=1。 现在假设B的序号为w(在B的半关闭状态有向A发送了一些数据),B还是必须重复上次已经发送过的确认号ack = u+1; 这是B就进入到了LAST-ACK(最后确认)状态 ,等待A的确认。
A在收到B的连接释放报文段后,必须对此发出确认。 在确认报文段中吧ACK置1。确认号ack=w+1。然后进入到TIME-WAIT(时间等待)状态。现在TCP还没有正在的释放掉,必须等待时间等地计时器(TIME-AWIT timer)设置的时间2MSL后,A进入到CLOSED状态。 时间MSL叫做最长报文寿命(Maximum Segment Lifetime)。标准推荐为2分钟。 等待4分钟之后,撤销相应的传输控制块TCB,就结束了本次连接。 - 为何A在TIME-WAIT状态等待2MSL?两个理由
- 保证A发送的最后一个ACK报文能够到达B。如果B没有收到,A就会超时重传,重新启动2MSL计时器,B就可以在2MSL时间内收到这个FIN+ ACK的确认段。如果没有2MSL计时器,B如果没有收到A的确认, B就无法正常的进入到CLOSED阶段。 造成资源的浪费
再次防止,已失效的请求连接报文段
A在发送完ACK报文段后,在经过2MSL,就可以使得本连接持续的时间产生的所有报文从网络中消失。可以使得下一次连接中不会出现旧的请求连接报文。