在计算机网络上进行通信的真正实体是位于通信两端的主机中的进程。运输层协议又称为
端到端
协议。
运输层的协议概述
1. 进程之间的通信
运输层向它上面的应用层提供
端到端通信服务
。进行端到端通信时,只有主机的协议栈才有运输层,而网络核心部分中的路由器在转发分组时都只用到下三层的功能。
既然IP协议能够将源主机发送出的分组按照首部中的目的地址送到目的主机,那么为什么还要再设置一个运输层呢?
从IP层来说,通信的两端是两个主机。IP数据报的首部明确的标志了这两个主机的IP地址。IP协议虽然能把分组送到目的主机,但是这个分组还停留在主机的网络层而没有交付给主机中的应用进程。从运输层的角度看,
通信的真正端点并不是主机而是主机中的进程。
因此,端到端的通信是应用程序之间的通信。
下图两个运输层之间有一个双向粗箭头,写明 “
运输层提供应用进程间的逻辑通信
”。“ 逻辑通信 ”的意思是:
运输层之间的通信好像是沿水平方向传送数据,但事实上这两个运输层之间并没有一条水平方向的物理连接,要传送的数据是沿着图中上下多次的虚线方向传送的
。
简单介绍以下运输层的
复用
(multiplexing)和
分用
(的multiplexing)功能。主机A的应用进程AP1和主机B的应用进程AP3通信,同时,应用进程AP2也和对方的应用进程AP4通信。这里的 “ 复用 ” 指发送方不同的应用进程都可以使用同一个运输层协议传送数据(加上适当的首部), “ 分用 ” 指接收方的运输层在剥去报文的首部后能够把这些数据正确交付到目的应用进程。
运输层和网络层有很大区别。
网络层是为主机之间提供逻辑通信,而运输层为应用程序之间提供端到端的逻辑通信。
后面会讨论,运输层协议还可以在网络层协议之上实现许多其他重要功能,如可靠数据传输、流量控制、拥塞控制等。因特网的运输层为应用层提供了两种不同的运输协议,即
面向连接的TCP
和
无连接的UDP
。
运输层向高层用户屏蔽了下面网络核心的细节
(如网络拓扑、所采用的路由选择协议等),它使应用进程看见的就是好像在两个运输层实体之间有一条端到端的逻辑通信信道,但这条逻辑通信信道对上层的表现却因运输层使用的不同协议而有很大的差别。当运输层
采用面向连接的TCP协议时
,
尽管下面的网络不可靠
(即只提供尽最大努力服务),但这条逻辑通信信道就相当于
一条全双工的可靠信道
。但当运输层采用
无连接的UDP协议
时,这种逻辑通信信道仍是一条
不可靠信道
。
客户-服务器模式,客户是主动发起通信的进程,而服务器是被动接受通信请求的进程。
1.2 因特网的运输层协议
因特网的网络层为主机之间提供的逻辑通信服务是一种
尽最大努力交付的数据报服务
。也就是说,IP报文在传送过程中有可能出错、丢失或失序。因此,需要运输层为这类应用提供可靠的数据传输服务。
TCP/IP网络为上层应用提供了两个不同的运输协议。
(1)
用户数据报协议
(User Datagram Protocol,
UDP
)
(2)
传输控制协议
(Transmission Control Protocol,
TCP
)OSI术语,两个对等实体在通信时传送的数据单位叫作运输协议数据单元(Transport Protocol Data Unit,
TPDU
)。运输层协议分别称为
TCP报文段
和
UDP报文
或
用户数据报
。
UDP在传输数据之前
不需要先建立连接
。远地主机的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP却是一种最有效的工作方式。
TCP提供
面向连接的服务
。在传送数据之前必须先建立连接,数据传送结束后要释放连接。由于TCP要提供可靠的、面向连接的运输服务,因此不可避免地增加了许多开销(如确认、流量控制、计时器及连接管理等)。使协议数据单元的首部增大很多,还要占用许多的处理机资源。
1.3 运输层的复用与分用
应用层所有的应用进程都可以通过运输层再传送到IP层,这就是
复用
。运输层从IP层收到数据后必须交付给指明的应用进程。这就是
分用
。运输层要能正确地将数据交付给指定应用进程,就必须给每个应用进程赋予一个标志。在TCP/IP网络中,使用一种与操作系统无关的
协议端口号
(protocol port number)来实现对通信的应用程序的标志。
端口
是应用层和运输层之间接口的
抽象
,端口号是应用进程的运输层地址。因此,在运输协议数据单元(TCP报文段或UDP用户数据报)的首部中必须包含两个字段:
源端口号
和
目的端口号
。当运输层收到IP层交上来的数据,要根据其目的端口号来决定应当通过哪一个端口上交给目的应用进程。
不同的计算机,端口的具体实现方法的差异性取决于计算机的操作系统。端口概念:应用层的源进程将报文发送给运输层的某个端口,而应用层的目的进程从端口接收报文。端口用一个16位
端口号
(允许有65535个端口号)进行标志,但
端口号只具有本地意义
。在因特网的不同计算机中,相同的端口号是
没有联系
的。IP协议根据IP数据报中的协议字段定位到要交付的运输层协议,而相应的运输层协议需要根据协议数据单元中的目的端口号来确定要交付的应用进程。
由此可见,两个计算机中的进程要互相通信,不仅要知道对方的
IP地址
(为了找到对方的计算机),而且还要知道对方的
端口号
(为了找到对方计算机中的应用进程)。应用进程间的通信采用的是客户-服务器模式,在应用层中的各种不同的服务器进程不断地监听它们的端口,以便发现是否有某个客户进程要和它通信。客户在发起通信请求时,必须首先知道对方服务器的IP地址和端口号,而服务器可以从接受到的报文中获取客户的IP地址和端口后。
用户数据报协议UDP
2.1 UDP概述
UDP只在IP的数据报服务之上增加了一些功能,端口的功能(有了端口,运输层就能进行复用和分用)和差错检验的功能。虽然UDP用户数据报提供不可靠的交付,但UDP在某些方面有其特殊的优点:
-
UDP是
无连接
的。发送数据前不需要建立连接,减少了开销和发送数据的时延。 -
UDP使用
尽最大努力交付
。不保证可靠交付,也不使用流量控制和拥塞控制,因此主机不需要维持具有很多参数的、复杂的连接状态表。 -
UDP
没有拥塞控制
,因此网络出现的拥塞不会使源主机的发送速率降低。如IP电话、实时视频会议等。要求源主机以恒定的速率发送数据,并允许在网络拥塞时丢失一些数据。 -
UDP是
面向报文
的。UDP不再对接受到的报文分组发送,也不会把收到的若干个报文合并后再交付给应用程序。因此,应用程序要选择合适的大小报文。若选择的太长,在IP层在传输时可能进行分片。报文太短,会使IP层数据报的首部相对太大,降低效率。 - UDP支持一对一、一对多、多对一和多对多的交互通信。
- 用户数据报只有8个字节的首部开销,比TCP的20个字节的首部要短的多。
5.2 UDP的首部格式
UDP报文有两个字段:数据字段和首部字段。首部字段由8个字节(4个字段)组成。各字段意义:(1)
源端口
源端口号。(2)
目的端口
目的端口号。(3)
长度
UDP用户数据报的长度。(4)
检验和
差错检验码,防止UDP用户数据报在传输中出错。
UDP报文首部中最重要的字段是源端口和目的端口。用来标识UDP的发送方和接收方。
二元组(IP地址、端口号)称为
套接字
(socket)地址。5-6中,UDP端口与一个报文队列(缓存)关联,UDP根据目的端口号将到达的报文加到对应的队列。可能会出现队列溢出和报文丢失现象。如果接收方UDP发现收到的报文中的目的端口号不正确(即不存在端口号所对应的进程),就丢弃该报文,然后网际控制报文协议ICMP发送“端口不可达”差错报文给发送方。
伪首部:计算检验和时,要在UDP用户数据报之前增加12个字节的
伪首部
。伪首部并不是UDP用户数据报真正的首部。检验和是按照这个临时的UDP用户数据报来计算的。仅仅为了计算检验和,防止报文被恶意地交付到错误的目的地。
UDP计算检验和的方法和计算IP数据报首部检验和的方法类似。不同的是:IP数据报的检验和只检验IP数据报的首部,但UDP的检验和是
把首部和数据部分一起都检验
。
传输控制协议TCP
3.1 TCP的主要特点
TCP提供全双工和可靠交付的服务。TCP和UDP最大的区别:
TCP是面向连接的,UDP是面向无连接的
。TCP除了具有面向连接和可靠传输的特性外,TCP还在运输层使用了
流量控制
和
拥塞控制机制
。
TCP主要的几个特点:
-
TCP是面向连接的运输层协议
。应用程序在使用TCP提供的服务传输数据之前,必须先建立TCP连接。为通信双方接下来的数据传送做准备,初始化状态变量、分配缓存等。传输完后必须释放TCP连接,即释放相应的资源和变量(和打电话类似) -
每一条TCP连接只能有两端点,
即每一条TCP连接只能是点对点的(一对一)。TCP连接唯一地被通信两端的端点(二元组)所确定,即一条TCP连接由两个套接字(socket)地址标识。 -
TCP提供可靠交付的服务
。通过TCP连接传送的数据无差错、不丢失、不重复,并且按序到达。 -
TCP提供
全双工通信
。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端有发送缓存和接收缓存,用来临时存放双向通信的数据。在发送/接收时,应用程序把数据传送给TCP的缓存 / TCP把收到的数据放入缓存,就可以做自己的事,在合适的时候发送出去/读取缓存中的数据。 -
面向字节流
。TCP中的“流”(stream)指的是流入到进程或进程流出的字节序列。“ 面向字节流 ”的含义是:虽然应用程序和TCP的交互式一次一个数据块(大小不等) ,但TCP把应用程序交下来的数据看成是一连串的
无结构的字节流
。接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。
TCP的接收方应用程序读取的数据块的边界与发送方应用程序发送的数据边界毫无关系,也就是说TCP接收方在向上层交付数据时不保证发送方应用程序发送数据块的边界。
图 5-7 中的TCP连接是一条虚连接,而不是物理连接。TCP连接是一种抽象的
逻辑连接
。
TCP报文段首先要传送到IP层,
加上IP层首部
后,再传送到数据链路层,再
加上数据链路层的首部和尾部
后,才离开主机发送到物理链路。另外,TCP连接仅存在于两个端系统中,而网络核心的中间设备(路由器、交换机等)完全
不知道该连接存在
。TCP连接的组成包括:通信两端主机上的缓存、状态变量,在这两台主机间的路由器和交换机没有为该连接分配任何缓存和变量。
与UDP端口队列不同的是,TCP的发送缓存和接收缓存都是分配给
一个连接
的,而不是一个端口。TCP的一个连接由
四元组
(
源IP地址、源端口号、目的IP地址、目的端口号
)标识。也就是说,来自不同源的TCP报文段,即使它们的目的IP地址和目的端口号相同,它们也不可能被交付到同一个TCP接收缓存中,因为它们在不同的TCP “ 管道 ” 中传输,到达不同 “ 管道 ” 出口的缓存。通常一个TCP服务器进程用一个端口号与不同的客户机进程建立多个连接,然后创建多个子进程分别用这些连接与各自的客户机进程进行通信。
3.2 TCP报文段结构
TCP 最然是面向字节流的,但TCP传送的数据单元却是报文段。TCP报文段分为首部和数据两部分,而TCP的全部功能体现在它
首部
中各字段的作用。TCP报文段首部的
前20个字节是固定
的,后面有4N个字节是根据需要而添加的选项(N必须为整数)。因此TCP首部最小长度是20字节。
首部固定各字段的意义:
-
源端口和目的端口
各占2个字节。与UDP一样,该字段定义了在主机中发送和接收该报文段的应用程序的接口,用于运输层的复用和分用。 -
序号
占4个字节。序号0–2的32次方-1。TCP是面向数据流的。TCP传送的报文段可看成连续的数据流。 -
确认号
占4个字节,是
期望收到对方的下一条报文段的第一个数据字节的序号
。 -
数据偏移
就是TCP报文段首部的长度。 -
保留
保留为今后使用 -
紧急 URG
(URGent)当URG=1时,表明紧急指针字段有效,告诉TCP此报文段有紧急数据 -
确认ACK
当ACK=1时,确认字段有效。 -
推送PSH
(PUSH)出于效率考虑,TCP可能会延迟发送数据或向应用程序延迟交付数据 -
复位RST
(ReSeT)RST=1时,表明TCP连接中出现严重差错 -
同步SYN
用来建立一个连接,当SYN=1,ACK=0时,表示连接请求报文段。若同意建立连接,SYN=1,ACK=1 -
终止FIN(FINal)
释放一个连接,报文段的发送方的数据发送完毕 -
窗口
占2字节。窗口字段控制
对方
发送的数据量,反映了接收方接受缓存的大小。计算机网络常
用接收方的接受能力的大小来控制发送方的数据发送量
。如:确认号701,窗口字段是1000允许对方发送数据的序号范围是701–1700 -
检验和
占2字节。检验和字段检验的范围包括首部和数据两部分。 -
选项
长度可变。
最大报文段长度
(Maximum Segment Size,MSS)MSS告诉TCP:我的缓存所能接收的报文段的
数据字段
的最大长度是MSS个字节
5.3 TCP的可靠传输
因特网的网络层是不可靠的,即通过IP层传送的数据可能出现差错、丢失、乱序或重复。TCP是如何实现可靠传输的?
1.数据编号与确认
TCP协议是
面向字节
的。TCP把应用层交下来的长报文(这可能要划分为许多较短的报文段,)看成是
一个个字节组成的数据流
,并
使每一个字节对应于一个序号
。在建立连接时,双方TCP要各自确定
初始序号
。TCP每次发送的报文段的首部中的序号字段数值表示该报文段中紧接着首部后面的
第一个数据字节的序号
。
TCP使用的是
累积确认
,即确认是
对是所有按序收到的数据的确认
。但接收方返回的确认号是已按序收到的数据的最高序号加1
表示接收方期望下次收到的数据中的第一个数据字节序号
。
TCP发送一段报文段时,同时也在自己的重传队列中存放这个报文段的一个副本。收到确认后,删除此副本;规定时间内没收到,则重传报文段的副本。
TCP的连接是全双工通信,可以在传送数据时顺便把确认信息
稍带
传送。
收到的报文段无差错,只是未按序到达,那么应如何处理?
在GBN中会丢弃所有未按序列到达的分组,但TCP是让实现者自行决定。多数TCP实现是现将其暂存与接收缓存内,待所缺的报文段收齐后一起上交应用层。
TCP发送方每发送一个报文段,就会为这个报文段设置一个计时器。TCP发送方只会重传超时的那一个分组。GBN会重传发送窗口内所有已发送的分组。
2.以字节为单位的滑动窗口
为了提高报文段的传输效率,TCP采用
滑动窗口
协议。但与GBN不用,TCP发送窗口大小的单位是
字节
,而不是分组数。TCP发送方已发送但未确认的字节数不能超过不能超过发送窗口的大小。
TCP的滑动窗口是会不断变化的,TCP的流量控制和拥塞控制会根据情况动态地调整发送窗口的上限制,从而控制发送数据的平均速率。
发送缓存用来暂时存放:
- 发送应用程序传送给发送方TCP准备发送的数据;
- TCP已发送出去但尚未收到确认的数据。
接收缓存用来暂时存放:
- 按序到达的,但尚未被接收应用程序读取的数据;
- 未按序到达的,但还不能被接收应用程序读取的数据。
如果收到的分组被检测出有差错,则要丢弃。如果接受应用程序不及时读取数据,接收缓存最终就会被填满,使接收窗口减小到零。
3. 超时重传时间的选择
TCP的发送方在规定时间内没有收到确认就要重传已发送的报文段。但如何选择超时重传的时间?
运输层的超时计时器的超时重传时间究竟设置多大?
显然超时重传时间要比当前报文段的
往返时间
(Round-Trip Time,
RTT
)要长一些。TCP采用自适应算法。该算法记录每一个报文段发出的时间,以及收到相应的确认报文段时间,这两个时间之差就是
报文段
的
往返
时间
RTT
。TCP采用指数加权移动平均的算法对RTT测量值进行加权平均,得出
报文段的平均往返时间RTTs
。
4. 快速重传
当一个报文段丢失时,发送方需要等待很长时间才能重传丢失的报文段,因而增加了端到端时延。但有时一个报文段的丢失会引起发送方连续收到多个重复的确认,通过这个判断报文段可能已经丢而不必等房贷重传计时器超时。
快速重传算法,发送方收到
一连三个重复的确认
后,就应立即重传丢失的报文段M2(注:重复确认的确认号正式要重传的报文段的序列号),而不必继续等待为M2设置的重传计时器的超时。尽早重传丢失的报文段。
5. 选择确认
TCP的报文段的确认字段是一种累积确认,它只通告收到的最后一个按序列到达的字节,而没有通告所有收到的失序到达的那些字节,虽然这些字节已经被接收方接收并暂存在接收缓存中。这些没有被确认的字节可能会因为超时而被发送方重传。所以一个可选的功能
选择确认
(Selective ACK,SACK)可以解决。
可以看出,每一个字节块需要用两个边界序号来标识。TCP在首部提供了一个 可 变 长的 “ SACK选项字段 ”来存放这些信息。除此之外,要使用选择确认功能,在建立TCP连接时,双方还要分别在SYN报文段和SYN+ACK报文段的首部选项中添加“允许SACK选项字段”,表示都支持选择确认功能。
3.4 TCP的流量控制
TCP为应用程序提供了
流量控制(flow control)服务
,
以解决因发送方发送数据太快而导致接收方来不及接收,使接受方缓存溢出 的问题
。
流量控制的基本方法就是接收方根据自己的接收能力控制发送方的发送速率。TCP采用
控制发送方发送窗口大小
(发送窗口的上限就是TCP报文段首部窗口写入的数值大小)的方法来实现TCP连接上的
流量控制
。
当接收方的可用接收缓存大小不为0时,向发送方发送的窗口更新报文段丢失了会出现什么问题?
如果接收方一直没有数据要发送给发送方,则发送方将会永远等下去。
如果接收方应用程序发送数据的速度长时间大于接收方应用程序接收数据的速度,在发送方会出现什么情况呢?
会导致TCP发送方的缓存被填满。这时发送应用程序必须等待,直到发送缓存有可用的空间。
3.5 TCP的连接管理
TCP是面向连接的协议。TCP连接的三个阶段,即
连接建立(分配相应的资源,为通信做准备)、数据传送和连接释放(释放所占用的资源)
。注意:TCP的连接是运输层连接,只存在于通信的两个端系统中,而网络核心的路由器完全不知道它的存在。
1.TCP的连接建立
在连接过程一般要解决以下三个问题:
- 要使每一方能够确知对方的存在。
- 要允许双方协商一些参数(如最大报文段长度,最大窗口大小,服务质量等)。
- 能够对运输实体资源(如缓存大小,各状态变量,连接表中的项目等)进行分配和初始化。
连接建立采用的 “
三次握手
”(
three-way handshake
):
为什么要发送这第三个报文段呢?
主要是为了防止
已失效的连接请求报文
段突然又传送到了主机B,因而产生错误。
主机A发出连接请求,但因连接请求报文丢失而未收到确认。主机A再重传一次,后来得到了确认,建立了连接。数据传输完毕后,释放了连接。其中主机A发送的第二个到达了主机B。
由于主机A发出的第一个连接请求报文段在某些网络节点滞留的时间太长,以致延误到在这次的
连接释放以后
才传送到主机B。但主机B收到此失效的连接请求报文段后,就误认为是主机A又发出的一次新的连接请求。于是就向主机A发出确认报文段,建立连接。
主机A由于没有要求建立连接,因此不会理睬主机B的确认,也不会向主机B发送数据。但主机B却以为运输连接就这样建立了,并一直等待主机A发来数据。主机B的许多资源就这样白白浪费了。
采用三次握手的办法可以防止上述现象发生。例如,在刚才情况下,主机A不会向主机B的确认发出确认。主机B收不到确认,连接就建立不起来。
2. TCP的连接释放
在数据传输结束后,通信的双方都可以发出释放连接的请求。在连接释放过程中要释放为该连接分配的所有资源。
主机A的应用进程先向其TCP发出连接释放请求。并且不再发送数据。TCP通知对方要释放从A到B的连接,把发往主机B的报文段首部的FIN置1,
序号seq=u
。由于
FIN报文段要消耗一个序号
,因此序号u等于A前面已传送过的数据的最后一个字节的序号加1。
主机B的TCP收到释放连接通知后即发出确认,
确认号是ack=u+1
,而这个报文段
自己的序号假定为v
(v等于B前面已传送数据最后一个字节的序号加1)。主机B的
TCP这时通知最高层应用程序
(箭头1)。这样,A到B的连接就释放了,连接处于
半关闭
(half-close)状态,相当于主机A向主机B说:我已经没有数据要发送了。但如果你还发送数据,我仍可以接收。
主机B不再接收主机A发来的数据。但若主机B还有一些数据要发往主机A,则可以继续发送(情况少)。主机A只要正确收到数据,仍应向主机B发送确认。
主机B不再向主机A发送数据,其
应用程序就通知TCP释放连接
(箭头2)。主机B发出的连接释放报文段必须
使FIN=1
,并使
其序号仍未v
(因为前面发送的确认报文段不消耗序号),还必须重复上次已发送过的
确认号ack=u+1
。
主机A必须对此发出确认,把
ACK置1
,
确认号ack=v+1
,
自己的序号是seq=u+1
(因为根据TCP标准,前面发送过的
FIN报文段要消耗一个序号
)。这样才能把B到A的反方向连接释放。
但此时,主机A的TCP并不能马上释放掉整个连接,还要再等待一个
超时时间
才能将整个连接释放。因为
主机A的确认有可能丢失
,这时主机B会重传FIN报文段。在这段超时时间内,若A又收到重传的FIN报文段,A需要再次进行确认。收到A的最后确认,B才能最终将整个连接释放。若超时时间内没有收到主机B的FIN报文段,主机A的TCP则向其应用进程报告,连接全部释放。
3.有限状态机
拥塞控制
当网络中出现太多的分组时,网络的性能开始下降。这种情况称为
拥塞
(congestion)。拥塞是分组交换网中一个非常重要的问题。如果网络中的
负载
(load),即发送到网络中的数据量超过了网络的容量(网络中能处理的数据量),那么在网络中过就可能发生拥塞。所谓
拥塞控制
(congestion control)就是
防止过多而数据注入到网络中,这样可以使网络中的路由器或链路不致过载。
拥塞的原因及危害:
当输入负载继续增大时,网络的吞吐量可能下降到0,即网络无法工作。这就是
死锁
(deadlock)。
A和C速率都是100Mbit/s分别向B和D发送数据,A和C在R1到R2共享链路上
各自获得50Mbit/s
的带宽。但由于R2到D的链路带宽只有10Mbit/s, C在路由器R2
损失40Mbit/s
。虽然路由器R2到B的带宽充足,但
A却无法充分使用
,只能50Mbit/s的速率传递数据。网络所能达到的
实际吞吐量只有60Mbit/s
。这就出现了
网络拥塞
(网络性能变差,资源被浪费)。
当网络拥塞而丢弃分组时,该分组在其经过路径中所占用的全部资源(链路带宽)都拜拜浪费掉了。
拥塞控制的基本方法
拥塞控制和流量控制之间的区别。它们都需要控制源点的发送速率。
拥塞控制的任务是防止过多的数据注入到网络中,使网络能够承受现有的网络负载。这是一个全局性的问题。
流量控制只与特定点对点通信的发送方和接收方之间的流量有关。它的任务是,确保一个快速的发送方不会持续地以超过接收方能力的速率发送数据,以防止接收方来不及处理数据。通常所涉及的做法是,接收方向发送方提供某种直接的反馈,以抑制发送方的发送速率。
TCP的拥塞控制