运输层的责任:运输层协议具有几种责任。一种责任就是创建进程到进程的通信(进程就是正在运行的应用程序),UDP使用端口号来完成这种通信。另一种责任就是在运输层提供流控制机制。运输层应当负责为进城提供链接机制,这些进程应当能够向运输层发送数据流,发送器运输层的责任应是和接收器运输层之间建立连接,将数据分割成为可运输的单元,将他们编号,然后逐个发送他们。运输层在接收端的责任应该是等待所有不同单元的到达,检查并传递那些没有差错的单元,并将他们作为一个流交付给接收进程。当整个流发送完毕后,运输层应该关闭这个链接。
UDP叫做无连接的,不可靠的运输协议。它除了提供进程到进程的通信(而不是主机到主机的通信)外,就没有给IP服务添加任何东西。此外,它还完成非常有限的差错检验。
IP是负责在计算机级的通信(主机到主机的通信)。作为网络层协议,IP只能将报文交付给计算机。但是,这是一种不完整的交付,这个报文还必须送交到正确的进程。这正是像UDP这样的运输层协议所要做的事,UDP就是负责将报文交付给适当的进程。
本地计算机上的叫做客户进程,需要从通常是在远程计算机上的叫做服务器的进程得到服务。这两个进程具有同样的名字(客户和服务器)具有相同的名字。例如,若要从远程服务器上得到日期和时间,我们需要在本地主机上运行DAYTIME的客户进程和在远程主机上运行DAYTIME的服务器进程。本地主机和远程主机用IP地址来定义。进程通过端口号来定义。客户程序定义它的端口号可通过随机来产生,但是服务器的端口号不能是随机产生的。
一个IP地址加上端口号就是一个SOCKET接口。它可以定义指定主机上的指定进程。
以下是一些常用的熟知端口号:
UDP用户数据报的格式
长度:这是一个16位字段,它定义了用户数据报的总长度,首部加上数据。
我们已经说到了端口,但是却还没有讨论端口实际上的实现。在UDP中,队列是与端口相关联在一起的。
在客户端,当进程启动时,它从操作系统请求一个端口号,有的实现是创建一个入队列和一个出队列与进程相关联,而有的实现是创建与每一个进程相关联的入队列。
应注意的是,甚至当一个进程想和多个进程通信时,它也只得到一个端口号,而最后也只有一个出队列和一个入队列。
客户进程使用在请求中指明的源端口号将报文发送到出队列。UDP逐个将报文取出,加上UDP首部,交付给IP。出队列可能出现溢出。要是发生溢出,则操作系统就要求客户进程在继续发送报文之前要等待。
当报文到达客户端时,UDP要检查一下,对应于该用户数据报中目的端口号字段指明的端口号有没有入队列被创建了。若有这样的队列,UDP就将受到的数据报放在该队列的末尾。若没有这样的队列,UDP就丢弃该数据报,并请求ICMP协议向服务器端发送不可达报文。所有发送给一个特定程序的入报文,不管事来自同样的或不同的服务器,都被放入同一个入队列。
在服务器端,创建队列的机制是不同的。但是,在最简单的情况下,服务器在它开始运行时就用它的熟知端口创建入队列和出队列。
UDP的设计
UDP软件包括一个控制块表、若干个输入队列、一个控制块模块、一个输入模块和一个输出模块。
控制块表:UDP有一个控制块表来记录打开的端口。表中的每一个项目最小有4个字段:状态(可以使FREE或IN-USE)、进程ID、端口号以及相应的丢列号。
控制块模块:控制块模块负责管理控制块表。当系统启动时,它就从操作系统要一个端口号。进程将进城ID和端口号传递给控制块模块,以便在表中为该进程创建一个项目。
输入模块:输入模块从IP接收用户数据报。它查找控制块表,寻找具有具有和这个用户数据报同样端口号的项目。若这道这样的项目,模块就利用这项目中的信息将这个数据放入队列。若未找到这样的项目,它就产生ICMP报文。
输出模块:输出模块负责创建和发送用户数据报。