传输层的概述(也叫运输层):
从网络层来说,通信的两端是两个主机,但“两个主机之间的通信”这种说法还不够清楚。这是因为,真正进行通信的实体是在主机中的进程,是这个主机中的一个进程和另一个主机中的一个进程在交换数据(即通信)。因此严格地讲,两个主机进行通信就是两个主机中的应用进程互相通信。
比如微信要发送的消息是到达另一个微信程序。
IP协议虽然能把分组送到目的主机,但是这个分组还停留在主机的网络层而没有交付给主机中的应用进程。从运输层的角度看,通信的真正端点并不是主机而是主机中的进程。也就是说,端到端的通信是应用进程之间的通信。
在一个主机中经常有多个应用进程同时分别和另一个主机中的多个应用进程通信。例如,某用户在使用浏览器查找某网站的信息时,其主机的应用层运行浏览器客户进程。如果在浏览网页的同时,还要用电子邮件给网站发送反馈意见,那么主机的应用层就还要运行电子邮件的客户进程。
在图中,主机A的应用进程AP1和主机B的应用进程AP3通信,而与此同时,应用进程AP2也和对方的应用进程AP4通信。这表明运输层有一个很重要的功能——复用( multiplexing)和分用( demultiplexing)。
这里的“复用”是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据(当然需要加上适当的首部),而“分用”是指接收方的运输层在剥去报文的首部后能够把这些数据正确交付到目的应用进程。
上图中两个运输层之间有一个双向粗箭头,写明“运输层提供应用进程间的逻辑通信”。“逻辑通信”的意思是:运输层之间的通信好像是沿水平方向传送数据。但事实上这两个运输层之间并没有一条水平方向的物理连接。要传送的数据是沿着图中的虚线方向(经过多个层次)传送的。
运输层还要对收到的报文进行差错检测。在网络层,IP数据报首部中的检验和字段,只检验首部是否出现差错而不检查数据部分。
根据应用程序的不同需求,运输层需要有两种不同的运输协议,即面向连接的TCP和无连接的UDP。
另外,运输层向高层用户屏蔽了下面网络核心的细节(如网络拓扑、所采用的路由选择协议等),它使应用进程看见的就是好像在两个运输层实体之间有一条端到端的逻辑通信信道,但这条逻辑通信信道对上层的表现却因运输层使用的不同协议而有很大的差别。当运输层采用面向连接的TCP协议时,尽管下面的网络是不可靠的(只提供尽最大努力服务),但这种逻辑通信信道就相当于一条全双工的可靠信道。但当运输层采用无连接的UDP协议时,这种逻辑通信信道仍然是一条不可靠信道。
传输层的两个主要协议
TCPP运输层的两个主要协议都是因特网的正式标准,即
(1)用户数据报协议UDP( User Datagram Protoco)【RFC768】
(2)传输控制协议TCP( Transmission Control Protocol)【RFC793】
UDP在传送数据之前不需要先建立连接。远地主机的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP却是一种最有效的工作方式。
TCP则提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或多播服务。由于TCP要提供可靠的、面向连接的运输服务,因此不可避免地增加了许多的开销,如确认、流量控制、计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多的处理机资源。
传输层的端口
前面提到过了复用和分用两个概念。
举一个生活化的例子就是,在寄快递时,我们把快递都寄到一个快递点,快递点再把各各快递统一装车运输,我们就是复用了快递点。而快递到达一个站点需要派送时,快递被送到不同的小区和门牌号,就是分用。
运输层的复用和分用功能也是类似的。应用层所有的应用进程都可以通过运输层再传送到IP层,这就是复用。运输层从IP层收到数据后必须交付给指明的应用进程。这就是分用。显然,给应用层的每个应用进程赋予一个非常明确的标志是至关重要的。
在单个计算机中的进程是用进程标识符(一个不大的整数)来标志的。但是在因特网环境下,用计算机操作系统所指派的这种进程标识符来标志运行在应用层的各种应用进程则是不行的。这是因为在因特网上使用的计算机的操作系统种类很多,而不同的操作系统又使用不同格式的进程标识符。为了使运行不同操作系统的计算机的应用进程能够互相通信,就必须用统一的方法(而这种方法必须与特定操作系统无关)对TCP体系的应用进程进行标志。
但是,把一个特定机器上运行的特定进程指明为因特网上通信最后的终点还是不可行的。这是因为进程的创建和撤销都是动态的,通信的一方几乎无法识别对方机器上的进程。
另外,我们往往需要利用目的主机提供的功能来识别终点,而不需要知道具体实现这个功能的进程是哪一个(例如,要和因特网上的某个邮件服务器联系,并不一定要知道这个服务器功能是由目的主机上的哪个进程实现的)。
解决这个问题的方法就是在运输层使用协议端口号( protocol port number),或通常简称为端口(port)。这就是说,虽然通信的终点是应用进程,但我们只要把要传送的报文交到目的主机的某一个合适的目的端口,剩下的工作(即最后交付给目的进程)就由TCP来完成。
在UDP和TCP的首部格式中,它们都有源端口和目的端口这两个重要字段。当运输层收到IP层交上来的运输层报文时,就能够根据其首部中的目的端口号把数据交付给应用层的目的应用进程TCPP的运输层用一个16位端口号来标志一个端口。但端口号只具有本地意义,它只是为了标志本计算机应用层中的各个进程在和运输层交互时的层间接口。在因特网不同计算机中,相同的端口号是没有关联的。16位的端口号可允许有65535个不同的端口号,这个数目对一个计算机来说是足够用的。
由此可见,两个计算机中的进程要互相通信,不仅必须知道对方的IP地址(为了找到对方的计算机),而且还要知道对方的端口号(为了找到对方计算机中的应用进程)。这和我们寄信的过程类似。当我们要和某人写信时,就必须知道他的通信地址。在信封上会写明自己的地址。当收信人回信时,很容易在信封上看到发信人的地址。因特网上的计算机通信是采用客户服务器方式。客户在发起通信请求时,必须先知道对方服务器的IP地址和端口号。
因此运输层的端口号共分为下面的两大类。
端口号分类:
(1)服务器端使用的端口号
这里又分为两类,最重要的一类叫做熟知端口号well knownportnumber)或系统端口号,数值为0-1023.这些数值可在网址www.lana.org查到。
IANA把这些端口号指派给了TCPP最重要的一些应用程序,让所有的用户都知道。当种新的应用程序出现后,IANA必须为它指派一个熟知端口,否则因特网上的其他应用进程就无法和它进行通信。下面给出一些常用的熟知端口号:
另一类叫做登记端口号,数值为1024-49151。这类端口号是为没有熟知端口号的应用程序使用的。使用这类端口号必须在IANA按照规定的手续登记,以防止重复。
(2)客户端使用的端口号
数值为49152~65535。由于这类端口号仅在客户进程运行时才动态选择,因此又叫做短暂端口号。这类端口号是留给客户进程选择暂时使用。当服务器进程收到客户进程的报文时,就知道了客户进程所使用的端口号,因而可以把数据发送给客户进程。通信结束后,刚才已使用过的客户端口号就不复存在。这个端口号就可以供其他客户进程以后使用。
UDP协议
UDP概述
用户数据报协议UDP只在IP的数据报服务之上增加了很少一点的功能,这就是复用和分用的功能以及差错检测的功能。UDP的主要特点是:
(1)UDP是无连接的,即发送数据之前不需要建立连接(当然发送数据结束时也没有连接可释放),因此减少了开销和发送数据之前的时延。
(2)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表(这里面有许多参数)。
(3)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文,如图所示。
在接收方的UDP,对IP层交上来的UDP用户数据报,在去除首部后就原封不动地交付给上层的应用进程。也就是说,UDP一次交付一个完整的报文。因此,应用程序必须选择合适大小的报文。若报文太长,UDP把它交给IP层后,IP层在传送时可能要进行分片,这会降低IP层的效率。反之,若报文太短,UDP把它交给IP层后,会使IP数据报的首部的相对长度太大,这也降低了IP层的效率。
(4)UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。这对某些实时应用是很重要的。很多的实时应用(如IP电话、实时视频会议等)要求源主机以恒定的速率发送数据,并且允许在网络发生拥塞时丢失一些数据,但却不允许数据有太大的时延。UDP正好适合这种要求
(5)UDP支持一对一、一对多、多对一和多对多的交互通信。
(6)UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短虽然某些实时应用需要使用没有拥塞控制的UDP,但当很多的源主机同时都向网络发送高速率的实时视频流时,网络就有可能发生拥塞,结果大家都无法正常接收。因此,不使用拥塞控制功能的UDP有可能会引起网络产生严重的拥塞问题。
还有一些使用UDP的实时应用,需要对UDP的不可靠的传输进行适当的改进,以减少数据的丢失。在这种情况下,应用进程本身可以在不影响应用的实时性的前提下,增加些提高可靠性的措施,如采用前向纠错或重传已丢失的报文。
UDP的首部格式
用户数据报UDP有两个字段:数据字段和首部字段。首部字段很简单,只有8个字节,由四个字段组成,每个字段的长度都是两个字节。各字段意义如下:
(1)源端口源端口号。在需要对方回信时选用。不需要时可用全0。
(2)目的端口目的端口号。这在终点交付报文时必须要使用到
(3)长度UDP用户数据报的长度,其最小值是8(仅有首部)。
(4)检验和检测UDP用户数据报在传输中是否有错。有错就丢弃。
当运输层从IP层收到UDP数据报时,就根据首部中的目的端口,把UDP数据报通过相应的端口,上交最后的终点——应用进程。
如果接收方UDP发现收到的报文中的目的端口号不正确(即不存在对应于该端口号的应用进程),就丢弃该报文,并由ICMP发送“端口不可达”差错报文给发送方。
UDP用户数据报首部中检验和的计算方法有些特殊。在计算检验和时,要在UDP用户数据报之前增加12个字节的伪首部。所谓“伪首部”是因为这种伪首部并不是UDP用户数据报真正的首部。只是在计算检验和时,临时添加在UDP用户数据报前面,得到一个临时的UDP用户数据报。检验和就是按照这个临时的UDP用户数据报来计算的。伪首部既不向下传送也不向上递交,而仅仅是为了计算检验和。
UDP计算检验和的方法和计算IP数据报首部检验和的方法相似。但不同的是:IP数据报的检验和只检验IP数据报的首部,但UDP的检验和是把首部和数据部分一起都检验。在发送方,首先是先把全零放入检验和字段。再把伪首部以及UDP用户数据报看成是由许多16位的字串接起来。若UDP用户数据报的数据部分不是偶数个字节,则要填入一个全零字节(但此字节不发送)。然后按二进制反码计算出这些16位字的和。将此和的二进制反码写入检验和字段后,就发送这样的UDP用户数据报。在接收方,把收到的UDP用户数据报连同伪首部(以及可能的填充全零字节)一起,按二进制反码求这些16位字的和。当无差错时其结果应为全1,否则就表明有差错出现,接收方就应丢弃这个UDP用户数据报(也可以上交给应用层,但附上出现了差错的警告)。
这里假定用户数据报的长度是15字节,因此要添加一个全0的字节。读者可以自己检验下在接收端是怎样对检验和进行检验的。不难看出,这种简单的差错检验方法的检错能力并不强,但它的好处是简单,处理起来较快。
伪首部的第3字段是全零,第4个字段是IP首部中的协议字段的值。对于UDP,此协议字段值为17,第5字段是UDP用户数据报的长度。因此,这样的检验和,既检査了UDP用户数据报的源端口号和目的端口号以及UDP用户数据报的数据部分,又检查了IP数据报的源IP地址和目的地址。