用户数据报协议UDP只在IP的数据报服务之上增加了很少一点的功能:复用、分用、差错检测。
(1)UDP是无连接的,即发送数据之前不需要建立连接(当然,发送数据结束时也没有连接可释放),因此减少了开销和发送数据之前的时延。
(2)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表(这里面有许多参数)。
(3)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,即不合并也不拆分,而是保留这些报文的边界。若报文太长,UDP把它交付给IP层,IP层在传送时可能要进行分片,这会降低IP层的效率。反之,若报文太短,UDP把它交给IP层,会使IP数据报的首部的相对长度太大,这也降低了IP层的效率。
(4)UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。UDP很好适合实时应用(如IP电话、实时视频会议等,实时应用要求源主机以恒定的速率发送数据,并且允许在网络发生拥塞时丢失一些数据,但却不允许数据有太大的时延)。
(5)UDP支持一对一、一对多、多对一和多对多的交互通信。
(6)UDP的首部开销小,只有8字节,比TCP的20个字节的首部要短。
UPD的首部格式
用户数据报UDP有两个字段:数据字段和首部字段。
首部字段8字节,由四个字段组成,每个字段的长度都是两个字节。
(1)源端口 源端口号。在需要对方回信时选用。不需要时可用全0。
(2)目的端口 目的端口号。这在终点交付报文时必须要使用到。
(3)长度 UDP用户数据报的长度,其最小值是8(仅有首部)。
(4)检验和 检验UDP用户数据报在传输中是否有错。有错就丢弃。
当运输层从IP层收到UDP数据报时,根据首部中的目的端口,把UDP数据报通过相应的端口,上交最后的终点---应用进程(即端口分用)。
如果接收方UDP发现收到的报文中的目的端口号不正确(即不存在对应于该端口号的应用进程),就丢弃该报文,并由网际控制报文协议ICMP发送“端口不可达”差错报文给发送方。
注意:在ICMP的应用举例中,讨论traceroute时,就是让发送的UDP用户数据报故意使用一个非法的UDP端口,结果ICMP就返回“端口不可达”差错报文,从而达到了测试的目的。
UDP用户数据报首部中检验和的计算方法:在数据报之前增加12字节的伪首部。
所谓的“伪首部”就是这种伪首部即不向下传送也不向上递交,仅作计算检验和用。
UDP的检验和是把首部和数据部分一起都检验。
把UDP用户数据报连同伪首部(以及可能的填充全零字节)一起,按二进制反码求这些16位字的和。再得出检验和写入首部。检验时仍求16位字的反码和,结果为全1时无差错。这种简单的差错检验方法的检错能力并不强,但它的好处是简单,处理起来较快。
伪首部的第3字段是全零,第4字段是IP首部中的协议字段的值,对于UDP,此协议字段值为17。
传输控制协议TCP
TCP是TCP/IP体系中非常复杂的一个协议。
(1)TCP是面向连接的运输层协议。应用程序在使用TCP协议之前,必须先建立TCP连接。
(2)每一条TCP连接只能有两个端点(endpoint),每一条TCP连接只能是点对点的(一对一)。
(3)TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达。
(4)TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据
(5)面向字节流。TCP中的"流"(stream)指的是流入到进程或从进程流出的字节序列。“面向字节流”的含义是:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系(即发送方可能发送了10个数据块,但接收方可能只用了4个数据块就把数据上交了,但总数据量相同)。
TCP连接是一条虚连接(也就是逻辑连接)而不是一条真正的物理连接。TCP报文段先要传送到IP层,加上IP首部后,再传送到数据链路层。再加上数据链路层的首部和尾部后,才离开主机发送到物理链路。
TCP并不关心应用进程一次把多长的报文发送到TCP的缓存中,而是根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应包含多少个字节(UDP发送的报文长度是应用进程给出的)。如果应用进程传送到TCP缓存的数据块太长,TCP就可以把它划分短一些再传送。如果应用进程一次只发来一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。(数据很少的时候,应该有一个等待时间(数据少)超时后发送)
TCP把连接作为最基本的抽象
TCP连接的端点叫做套接字(socket)或插口。端口号拼接到IP地址即构成了套接字。
套接字socket = (IP地址:端口号)
每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定。
TCP连接 ::= { socket1,socket2 } = {(IP1:port1),(IP2 : port2)}
TCP连接就是由协议软件所提供的一种抽象。TCP连接的端点是个很抽象的套接字,同一个IP地址可以有很多个不同的TCP连接,而同一个端口号也可以出现在多个不同的TCP连接中。
同一个名词socket却可表示多种不同的意思。
(1)允许应用程序访问连网协议的应用编程接口API(Application Programming Interface),即运输层和应用层之间的一种接口,称为socketAPI,并简称为socket。
(2)在socketAPI中使用的一个函数名也叫作socket。
(3)调用socket函数的端点称为socket,如“创建一个数据报socket”
(4)调用socket函数时,其返回值称为iesocket描述符,可简称为socket。
(5)在操作系统内核中恋网协议的Berkeley实现,称为socket实现。
TCP报文段的首部格式
TCP虽然是面向字节流的,但TCP传送的数据单元却是报文段。TCP报文段首部的前20个字节是固定的,后面有4n字节是根据需要而增加的选项。
(2)序号 占4个字节。序号范围是[0,2^32 - 1],序号增加到2^32 - 1后,下一个序号就又回到0。TCP是面向字节流的。在一个TCP连接中传送的字节流中每一个字节都是按顺序编号。整个要传送的字节流的起始序号必须在连接建立是设置。首部中的序号字段值则指的是本报文段所发送的数据中的第一个字节的序号。
(3)确认号 占4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。
若确认号 = N,则表明:到序号N - 1为止的所有数据都已正确收到。
(5)数据偏移 占4位,指出TCP报文段的首部长度。
(6)保留 占6位,保留为今后使用,但目前应置为0。
(7)URG(URGent)紧急 当URG=1时,表明紧急指针字段有效。发送应用进程就告诉发送方的TCP有紧急数据要传送。于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。
(8)ACK(ACKnowlegment)确认 仅当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。
(9)PSH(PuSH)推送 当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去。接收方TCP收到PSH=1的报文段,就尽快地(即“推送”向前)交付接收应用进程,而不再等到整个缓存都填满了后面再向上交付。
(10)RST(ReSeT)复位 当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其它原因),必须释放连接,然后在重新建立运输连接。RST置1还用来拒绝一个非法的报文段或拒绝打开一个连接。RST也可称为重建位或重置位。
(11)SYN(SYNchronization)同步 在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。因此,SYN置为1就表示这是一个连接请求或连接接受报文。
(12)FIN(FINis)终止 用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接。
(13)窗口 占2字节。窗口值是[0,2^16 - 1]之间的整数。窗口指的是发送本报文段的一方的接收窗口(而不是自己的发送窗口)。
窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。总之,窗口值作为接收方放发送方设置其发送窗口的依据。
窗口字段明确指出了现在允许对方发送的数据量。窗口值是经常在动态变化的。
(14)检验和 占2字节。检验和字段检验的范围包括首部和数据这两部分。检验方法和UDP一样。
(15)紧急指针 占2字节。指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。因此,紧急指针指出了紧急数据的末尾在报文段中的位置。值得注意的是,即使窗口为零时也可以发送紧急数据。
(16)选项 长度可变,最长可达40字节。
最大报文段长度MSS(Maximum Segment Size)选项、窗口扩大选项、时间戳选项、选择确认选项。
MSS是每一个TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个的TCP报文段。
问题:为什么要规定最大报文段长度MSS?是考虑接收方的接收缓存可能放不下TCP报文段中的数据?
解答:实际上,MSS与接收窗口值没有关系。TCP报文段的数据部分至少要加上40字节的首部(TCP首部20字节和IP首部20字节)才能组装成一个IP数据报。所以MSS过小导致网络的利用率很低,MSS过大导致在IP层运输时要分解成多个短数据报片。这样使两边的开销增大。
因为IP数据报所经历的路径是动态变化的,所以最佳的MSS是很难确定的。在连接建立的过程中,双方都把自己能够支持的MSS写入这一字段,以后就按照这个数值传送数据,两个传送方向可以有不同的MSS值。若主机未填写,MSS的默认值是536字节长。因此,所有在因特网上的主机都应能接受的报文段长度(这里指TCP报文)是536+20(固定首部长度)=556字节。
窗口扩大选项是为了扩大窗口。TCP首部中窗口字段的长度是16位,因此最大的窗口大小为64字节。对早期的网络是足够用的,但对于包含卫星信道的网络,传播时延和带宽都很大,要获得高吞吐率需要更大的窗口大小。
窗口苦大选项占3字节,其中有一个字节表示移位值S。新的窗口值等于TCP首部中的窗口位数从16增大到(16+S)。移位值允许使用的最大值是14,相当于窗口最大值增大到2^(16+14) - 1 = 2^30 - 1。
窗口扩大选项可以在双方初始化建立TCP连接时进行协商。如果连接的某一端实现了窗口扩大,当它不再需要扩大其窗口时,可发送S=0的选项,使窗口大小回到16。
时间戳选项占10字节,其中最主要的字段时间戳值字段(4字节)和时间戳回送回答字段(4字节)。时间戳选项有以下两个功能:
第一,用来计算往返时间RTT。发送方在发送报文段时把当前时钟的时间值放入时间戳字段,接收方在确认该报文段时把时间戳字段值复制到时间戳回送回答字段。因此,发送方在收到确认该报文段时把时间戳字段值复制到时间戳回送回答字段。因此,发送方在收到确认报文后,可以准确地计算出RTT来。
第二,用来处理TCP序号超过2^32的情况,这又称为防止序号绕回PAWS(Protect Against Wrapped Sequence numbers)。当使用高速网络时,在一次TCP连接的数据传送中序号很可能会被重复使用,为了使接收方能够把新的报文段和迟到很久的报文段区分开,可以在报文段中加上这种时间戳。
选择确认选项,将在之后详细介绍。