tcp/ip(十一)

来源:互联网 发布:兼职淘宝优惠卷 编辑:程序博客网 时间:2024/06/05 18:24

下载
第11章UDP:用户数据报协议
11.1 引言
U D P是一个简单的面向数据报的运输层协议:进程的每个输出操作都正好产生一个U D P
数据报,并组装成一份待发送的I P数据报。
这与面向流字符的协议不同,如T C P,应用
程序产生的全体数据与真正发送的单个I P数
据报可能没有什么联系。
U D P数据报封装成一份I P数据报的格式
如图11 - 1所示。
RFC 768 [Postel 1980] 是U D P的正式规
范。
U D P不提供可靠性:它把应用程序传给I P层的数据发送出去,但是并不保证它们能到达
目的地。由于缺乏可靠性,我们似乎觉得要避免使用U D P而使用一种可靠协议如T C P。我们
在第1 7章讨论完T C P后将再回到这个话题,看看什么样的应用程序可以使用U D P。
应用程序必须关心I P数据报的长度。如果它超过网络的M T U(2 . 8节),那么就要对I P数
据报进行分片。如果需要,源端到目的端之间的每个网络都要进行分片,并不只是发送端主
机连接第一个网络才这样做(我们在2 . 9节中已定义了路径M T U的概念)。在11 . 5节中,我们
将讨论I P分片机制。
11.2 UDP首部
U D P首部的各字段如图11 - 2所示。
图11-2 UDP首部
端口号表示发送进程和接收进程。在图1 - 8中,我们画出了T C P和U D P用目的端口号来分
用来自I P层的数据的过程。由于I P层已经把I P数据报分配给T C P或U D P(根据I P首部中协议字
段值),因此T C P端口号由T C P来查看,而U D P端口号由U D P来查看。T C P端口号与U D P端口
号是相互独立的。
图11-1 UDP封装
IP数据报
UDP数据报
首部
UDP
首部UDP数据
20字节8字节
16位源端口号16位目的端口号
16位UDP长度16位UDP检验和
数据(如果有)
8字节
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
尽管相互独立,如果T C P和U D P同时提供某种知名服务,两个协议通常选择相同
的端口号。这纯粹是为了使用方便,而不是协议本身的要求。
U D P长度字段指的是U D P首部和U D P数据的字节长度。该字段的最小值为8字节(发送一
份0字节的U D P数据报是O K)。这个U D P长度是有冗余的。I P数据报长度指的是数据报全长
(图3 - 1),因此U D P数据报长度是全长减去I P首部的长度(该值在首部长度字段中指定,如图
3 - 1所示)。
11.3 UDP检验和
U D P检验和覆盖U D P首部和U D P数据。回想I P首部的检验和,它只覆盖I P的首部—并不
覆盖I P数据报中的任何数据。
U D P和T C P在首部中都有覆盖它们首部和数据的检验和。U D P的检验和是可选的,而T C P
的检验和是必需的。
尽管U D P检验和的基本计算方法与我们在3 . 2节中描述的I P首部检验和计算方法相类似
(16 bit字的二进制反码和),但是它们之间存在不同的地方。首先, U D P数据报的长度可以为
奇数字节,但是检验和算法是把若干个16 bit字相加。解决方法是必要时在最后增加填充字节
0,这只是为了检验和的计算(也就是说,可能增加的填充字节不被传送)。
其次, U D P数据报和T C P段都包含一个1 2字节长的伪首部,它是为了计算检验和而设置
的。伪首部包含I P首部一些字段。其目的是让U D P两次检查数据是否已经正确到达目的地
(例如, I P没有接受地址不是本主机的数据报,以及I P没有把应传给另一高层的数据报传给
U D P)。U D P数据报中的伪首部格式如图11 - 3所示。
图11-3 UDP检验和计算过程中使用的各个字段
在该图中,我们特地举了一个奇数长度的数据报例子,因而在计算检验和时需要加上填
充字节。注意,U D P数据报的长度在检验和计算过程中出现两次。
如果检验和的计算结果为0,则存入的值为全1(6 5 5 3 5),这在二进制反码计算中是等效
的。如果传送的检验和为0,说明发送端没有计算检验和。
108使用TCP/IP详解,卷1:协议
下载
32位源IP地址
32位目的IP地址
0 8位协议(17) 16位UDP长度
16位目的端口号
16位UDP检验和
UDP首部
UDP伪首部
16位源端口号
16位UDP长度
数据
填充字节(0)
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
如果发送端没有计算检验和而接收端检测到检验和有差错,那么U D P数据报就要被悄悄
地丢弃。不产生任何差错报文(当I P层检测到I P首部检验和有差错时也这样做)。
U D P检验和是一个端到端的检验和。它由发送端计算,然后由接收端验证。其目的是为
了发现U D P首部和数据在发送端到接收端之间发生的任何改动。
尽管U D P检验和是可选的,但是它们应该总是在用。在8 0年代,一些计算机产商在默认
条件下关闭U D P检验和的功能,以提高使用U D P协议的N F S(Network File System)的速度。
在单个局域网中这可能是可以接受的,但是在数据报通过路由器时,通过对链路层数据帧进
行循环冗余检验(如以太网或令牌环数据帧)可以检测到大多数的差错,导致传输失败。不
管相信与否,路由器中也存在软件和硬件差错,以致于修改数据报中的数据。如果关闭端到
端的U D P检验和功能,那么这些差错在U D P数据报中就不能被检测出来。另外,一些数据链
路层协议(如S L I P)没有任何形式的数据链路检验和。
Host Requirements RFC声明,U D P检验和选项在默认条件下是打开的。它还声明,
如果发送端已经计算了检验和,那么接收端必须检验接收到的检验和(如接收到检验
和不为0)。但是,许多系统没有遵守这一点,只是在出口检验和选项被打开时才验证
接收到的检验和。
11.3.1 tcpdump输出
很难知道某个特定系统是否打开了U D P检验和选项。应用程序通常不可能得到接收到的
U D P首部中的检验和。为了得到这一点,作者在t c p d u m p程序中增加了一个选项,以打印出
接收到的U D P检验和。如果打印出的值为0,说明发送端没有计算检验和。
测试网络上三个不同系统的输出如图11 - 4所示(参见封面二)。运行我们自编的s o c k程序
(附录C),发送一份包含9个字节数据的U D P数据报给标准回显服务器。
图11-4 t c p d u m p 输出,观察其他主机是否打开UDP检验和选项
从这里可以看出,三个系统中有两个打开了U D P检验和选项。
还要注意的是,在这个简单例子中,送出的数据报与收到的数据报具有相同的检验和值
(第3和第4行,第5和第6行)。从图11-3可以看出,两个IP地址进行了交换,正如两个端口号一样。
伪首部和U D P首部中的其他字段都是相同的,就像数据回显一样。这再次表明U D P检验和(事
实上,TCP/IP协议簇中所有的检验和)是简单的16 bit和。它们检测不出交换两个16 bit的差错。
作者在1 4 . 2节中在8个域名服务器中各进行了一次D N S查询。D N S主要使用U D P,
结果只有两台服务器打开了UDP检验和选项。
11.3.2 一些统计结果
文献[Mogul 1992 ]提供了在一个繁忙的N F S服务器上所发生的不同检验和差错的统计结果,
第11章UDP:用户数据报协议使用109 下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
时间持续了4 0天。统计数字结果如图11 - 5所
示。
最后一列是每一行的大概总数,因为以
太网和I P层还使用其他的协议。例如,不是
所有的以太网数据帧都是I P数据报,至少以
太网还要使用A R P协议。不是所有的I P数据
报都是U D P或T C P数据,因为I C M P也用I P传送数据。
注意, T C P发生检验和差错的比例与U D P相比要高得多。这很可能是因为在该系统中的
T C P连接经常是“远程”连接(经过许多路由器和网桥等中间设备),而U D P一般为本地通信。
从最后一行可以看出,不要完全相信数据链路(如以太网,令牌环等)的C R C检验。应
该始终打开端到端的检验和功能。而且,如果你的数据很有价值,也不要完全相信U D P或
T C P的检验和,因为这些都只是简单的检验和,不能检测出所有可能发生的差错。
11.4 一个简单的例子
用我们自己编写的s o c k程序生成一些可以通过t c p d u m p观察的U D P数据报:
bsdi % sock -v -u -i -n4 svr4 discard
connected on 140.252.13.35.1108 to 140.252.13.34.9
bsdi % sock -v -u -i -n4 -w0 svr4 discard
connected on 140.252.13.35.1110 to 140.252.13.34.9
第1次执行这个程序时,我们指定v e r b o s e模式(- v)来观察e p h e m e r a l端口号,指定U D P
(- u)而不是默认的T C P,并且指定源模式( - i)来发送数据,而不是读写标准的输入和输
出。- n 4选项指明输出4份数据报(默认条件下为1 0 2 4),目的主机为s v r 4。在1 . 1 2节描述了丢
弃服务。每次写操作的输出长度取默认值1 0 2 4。
第2次运行该程序时我们指定- w 0,意思是写长度为0的数据报。两个命令的t c p d u m p输
出结果如图11 - 6所示。
图11-6 向一个方向发送UDP数据报时的t c p d u m p 输出
输出显示有四份1 0 2 4字节的数据报,接着有四份长度为0的数据报。每份数据报间隔几毫
秒(输入第2个命令花了4 1秒的时间)。
在发送第1份数据报之前,发送端和接收端之间没有任何通信(在第1 7章,我们将看到
T C P在发送数据的第1个字节之前必须与另一端建立连接)。另外,当收到数据时,接收端没
有任何确认。在这个例子中,发送端并不知道另一端是否已经收到这些数据报。
最后要指出的是,每次运行程序时,源端的U D P端口号都发生变化。第一次是11 0 8,然
后是11 0。在1 . 9节我们已经提过,客户程序使用e p h e m e r a l端口号一般在1 0 2 4~5 0 0 0之间,正
110使用TCP/IP详解,卷1:协议
下载
图11-5 检测到不同检验和差错的分组统计结果
层次
以太网
检验和差错数近似总分组数
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
如我们现在看到的这样。
11.5 IP分片
正如我们在2 . 8节描述的那样,物理网络层一般要限制每次发送数据帧的最大长度。任何
时候I P层接收到一份要发送的I P数据报时,它要判断向本地哪个接口发送数据(选路),并查
询该接口获得其M T U。I P把M T U与数据报长度进行比较,如果需要则进行分片。分片可以发
生在原始发送端主机上,也可以发生在中间路由器上。
把一份I P数据报分片以后,只有到达目的地才进行重新组装(这里的重新组装与其他网
络协议不同,它们要求在下一站就进行进行重新组装,而不是在最终的目的地)。重新组装由
目的端的I P层来完成,其目的是使分片和重新组装过程对运输层( T C P和U D P)是透明的,
除了某些可能的越级操作外。已经分片过的数据报有可能会再次进行分片(可能不止一次)。
I P首部中包含的数据为分片和重新组装提供了足够的信息。
回忆I P首部(图3 - 1),下面这些字段用于分片过程。对于发送端发送的每份I P数据报来说,
其标识字段都包含一个唯一值。该值在数据报分片时被复制到每个片中(我们现在已经看到
这个字段的用途)。标志字段用其中一个比特来表示“更多的片”。除了最后一片外,其他每
个组成数据报的片都要把该比特置1。片偏移字段指的是该片偏移原始数据报开始处的位置。
另外,当数据报被分片后,每个片的总长度值要改为该片的长度值。
最后,标志字段中有一个比特称作“不分片”位。如果将这一比特置1,I P将不对数据报
进行分片。相反把数据报丢弃并发送一个I C M P差错报文(“需要进行分片但设置了不分片比
特”,见图6 - 3)给起始端。在下一节我们将看到出现这个差错的例子。
当I P数据报被分片后,每一片都成为一个分组,具有自己的I P首部,并在选择路由时与
其他分组独立。这样,当数据报的这些片到达目的端时有可能会失序,但是在I P首部中有足
够的信息让接收端能正确组装这些数据报片。
尽管I P分片过程看起来是透明的,但有一点让人不想使用它:即使只丢失一片数据也要重
传整个数据报。为什么会发生这种情况呢?因为I P层本身没有超时重传的机制——由更高层来
负责超时和重传(T C P有超时和重传机制,但U D P没有。一些U D P应用程序本身也执行超时和
重传)。当来自T C P报文段的某一片丢失后,T C P在超时后会重发整个T C P报文段,该报文段对
应于一份I P数据报。没有办法只重传数据报中的一个数据报片。事实上,如果对数据报分片的
是中间路由器,而不是起始端系统,那么起始端系统就无法知道数据报是如何被分片的。就这
个原因,经常要避免分片。文献[Kent and Mogul 1987]对避免分片进行了论述。
使用U D P很容易导致I P分片(在后面我们将看到, T C P试图避免分片,但对于应用程序来
说几乎不可能强迫T C P发送一个需要进行分片的长报文段)。我们可以用s o c k程序来增加数
据报的长度,直到分片发生。在一个以太网上,数据帧的最大长度是1 5 0 0字节(见图2 - 1),
其中1 4 7 2字节留给数据,假定I P首部为2 0字节, U D P首部为8字节。我们分别以数据长度为
1471, 1472, 1473和1 4 7 4字节运行s o c k程序。最后两次应该发生分片:
bsdi % sock -u -i -nl -w1471 svr4 discard
bsdi % sock -u -i -nl -w1472 svr4 discard
bsdi % sock -u -i -nl -w1473 svr4 discard
bsdi % sock -u -i -nl -w1474 svr4 discard
相应的t c p d u m p输出如图11 - 7所示。
第11章UDP:用户数据报协议使用111 下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
图11-7 观察UDP数据报分片
前两份U D P数据报(第1行和第2行)能装入以太网数据帧,没有被分片。但是对应于写
1 4 7 3字节的I P数据报长度为1 5 0 1,就必须进行分片(第3行和第4行)。同理,写1 4 7 4字节产生
的数据报长度为1 5 0 2,它也需要进行分片(第5行和第6行)。
当I P数据报被分片后, t c p d u m p打印出其他的信息。首先,frag 26304(第3行和第4
行)和frag 26313(第5行和第6行)指的是I P首部中标识字段的值。
分片信息中的下一个数字,即第3行中位于冒号和@号之间的1 4 8 0,是除I P首部外的片长。
两份数据报第一片的长度均为1 4 8 0:U D P首部占8字节,用户数据占1 4 7 2字节(加上I P首部的
2 0字节分组长度正好为1 5 0 0字节)。第1份数据报的第2片(第4行)只包含1字节数据—剩下
的用户数据。第2份数据报的第2片(第6行)包含剩下的2字节用户数据。
在分片时,除最后一片外,其他每一片中的数据部分(除I P首部外的其余部分)必须是8
字节的整数倍。在本例中, 1 4 8 0是8的整数倍。
位于@符号后的数字是从数据报开始处计算的片偏移值。两份数据报第1片的偏移值均为0(第3行
和第5行),第2片的偏移值为1 4 8 0(第4行和第6行)。跟在偏移值后面的加号对应于I P首部中3 bit标志
字段中的“更多片”比特。设置这一比特的目的是让接收端知道在什么时候完成所有的分片组装。
最后,注意第4行和第6行(不是第1片)省略了协议名( U D P)、源端口号和目的端口号。
协议名是可以打印出来的,因为它在I P首部并被复制到各个片中。但是,端口号在U D P首部,
只能在第1片中被发现。
发送的第3份数据报(用户数据为1 4 7 3字节)分片情况如图11 - 8所示。需要重申的是,任
何运输层首部只出现在第1片数据中。
另外需要解释几个术语: I P数据报是指I P层端到端的传输单元(在分片之前和重新组装
之后),分组是指在I P层和链路层之间传送的数据单元。一个分组可以是一个完整的I P数据报,
也可以是I P数据报的一个分片。
图11-8 UDP分片举例
112使用TCP/IP详解,卷1:协议
下载
20字节
20字节
8字节
8字节
1472字节20字节1字节
IP首部UDP首部IP首部
IP首部UDP首部
IP数据报
UDP数据(1473字节)
分组分组
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
11.6 ICMP不可达差错(需要分片)
发生I C M P不可达差错的另一种情况是,当路由器收到一份需要分片的数据报,而在I P首
部又设置了不分片( D F)的标志比特。如果某个程序需要判断到达目的端的路途中最小M T U
是多少—称作路径M T U发现机制( 2 . 9节),那么这个差错就可以被该程序使用。
这种情况下的I C M P不可达差错报文格式如图11 - 9所示。这里的格式与图6 - 1 0不同,因为
在第2个32 bit字中,16~31 bit可以提供下一站的M T U,而不再是0。
图11-9 需要分片但又设置不分片标志比特时的ICMP不可达差错报文格式
如果路由器没有提供这种新的I C M P差错报文格式,那么下一站的M T U就设为0。
新版的路由器需求RFC [Almquist 1993]声明,在发生这种I C M P不可达差错时,路
由器必须生成这种新格式的报文。
例子
关于分片作者曾经遇到过一个问题, I C M P差错试图判断从路由器n e t b到主机s u n之间的
拨号S L I P链路的M T U。我们知道从s u n到n e t b的链路的M T U:当S L I P被安装到主机s u n时,
这是S L I P配置过程中的一部分,加上在3 . 9节中已经通过n e t s t a t命令观察过。现在,我们想
从另一个方向来判断它的M T U(在第2 5章,将讨论如何用S N M P来判断)。在点到点的链路中,
不要求两个方向的M T U为相同值。
所采用的技术是在主机s o l a r i s上运行p i n g程序到主机b s d i,增加数据分组长度,直
到看见进入的分组被分片为止。如图11 - 1 0所示。
图11-10 用来判断从n e t b 到s u n 的SLIP链路MTU的系统
在主机s u n上运行t c p d u m p,观察S L I P链路,看什么时候发生分片。开始没有观察到分
片,一切都很正常直到p i n g分组的数据长度从5 0 0增加到6 0 0字节。可以看到接收到的回显请
第11章UDP:用户数据报协议使用113 下载
类型(3) 代码(4) 检验和
8字节
未用(必须为0) 下一站网络的MTU
IP首部(包括选项)+原始IP数据报中数据的前8字节
分片
分片
用tcpdump观察分片
ICMP回显请求
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
求(仍然没有分片),但不见回显应答。
为了跟踪下去,也在主机b s d i上运行t c p d u m p,观察它接收和发送的报文。输出如图
11 - 11所示。
图11-11 600字节的IP数据报从s o l a r i s 主机p i n g 到b s d i 主机时的t c p d u m p 输出
首先,每行中的标记( D F)说明在I P首部中设置了不分片比特。这意味着Solaris 2.2 一
般把不分片比特置1,作为实现路径M T U发现机制的一部分。
第1行显示的是回显请求通过路由器n e t b到达s u n主机,没有进行分片,并设置了D F比
特,因此我们知道还没有达到n e t b的SLIP MTU。
接下来,在第2行注意到D F标志被复制到回显应答报文中。这就带来了问题。回显应答与
回显请求报文长度相同(超过6 0 0字节),但是s u n外出的S L I P接口M T U为5 5 2。因此回显应
答需要进行分片,但是D F标志比特又被设置了。这样, s u n就产生一个I C M P不可达差错报文
返回给b s d i(报文在b s d i处被丢弃)。
这就是我们在主机s o l a r i s上没有看到任何回显应答的原因。这些应答永远不能通过
s u n。分组的路径如图11 - 1 2所示。
图11-12 例子中的分组交换
最后,在图11 - 11中的第3行和第6行中,m t u = 0表示主机s u n没有在I C M P不可达报文中返
回出口M T U值,如图11 - 9所示(在2 5 . 9节中,将重新回到这个问题,用S N M P判断n e t b上的
S L I P接口M T U值为1 5 0 0)。
11.7 用Traceroute确定路径MTU
尽管大多数的系统不支持路径M T U发现功能,但可以很容易地修改t r a c e r o u t e程序
(第8章),用它来确定路径M T U。要做的是发送分组,并设置“不分片”标志比特。发送的
第一个分组的长度正好与出口M T U相等,每次收到I C M P“不能分片”差错时(在上一节讨论
114使用TCP/IP详解,卷1:协议
下载
ICMP回显请求
ICMP回显请求
ICMP回显请求
ICMP回显应答
ICMP不可达:需要分片,
但又设置了DF位
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
的)就减小分组的长度。如果路由器发送的I C M P差错报文是新格式,包含出口的M T U,那么
就用该M T U值来发送,否则就用下一个最小的M T U值来发送。正如RFC 1191 [Mogul and
Deering 1990]声明的那样, M T U值的个数是有限的,因此在我们的程序中有一些由近似值构
成的表,取下一个最小M T U值来发送。
首先,我们尝试判断从主机s u n到主机s l i p的路径M T U,知道S L I P链路的M T U为2 9 6。
在这个例子中,路由器b s d i没有在I C M P差错报文中返回出口M T U,因此我们选择另一个
M T U近似值。T T L为2的第1行输出打印的主机名为b s d i,但这是因为它是返回I C M P差错报
文的路由器。T T L为2的最后一行正是我们所要找的。
在b s d i上修改I C M P代码使它返回出口M T U值并不困难,如果那样做并再次运行该程序,
得到如下输出结果:
这时,在找到正确的M T U值之前,我们不用逐个尝试8个不同的M T U值——路由器返回
了正确的M T U值。
全球互联网
作为一个实验,我们多次运行修改以后的t r a c e r o u t e程序,目的端为世界各地的主机。
可以到达1 5个国家(包括南极洲),使用了多个跨大西洋和跨太平洋的链路。但是,在这样做
之前,作者所在子网与路由器n e t b之间的拨号S L I P链路M T U(见图11 - 1 2)增加到1 5 0 0,与
以太网相同。
在1 8次运行当中,只有其中2次发现的路径M T U小于1 5 0 0。其中一个跨大西洋的链路
M T U值为5 7 2(其近似值甚至在RFC 11 9 1中也没有被列出),而路由器返回的是新格式的
I C M P差错报文。另外一条链路,在日本的两个路由器之间,不能处理1 5 0 0字节的数据帧,并
且路由器没有返回新格式的I C M P差错报文。把M T U值设成1 0 0 6则可以正常工作。
从这个实验可以得出结论,现在许多但不是所有的广域网都可以处理大于5 1 2字节的分组。
利用路径M T U发现机制,应用程序就可以充分利用更大的M T U来发送报文。
第11章UDP:用户数据报协议使用115 下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
11.8 采用UDP的路径MTU发现
下面对使用U D P的应用程序与路径M T U发现机制之间的交互作用进行研究。看一看如果
应用程序写了一个对于一些中间链路来说太长的数据报时会发生什么情况。
例子
由于我们所使用的支持路径M T U发现机制的唯一系统就是Solaris 2.x,因此,将采用它作
为源站发送一份6 5 0字节数据报经s l i p。由于s l i p主机位于M T U为2 9 6的S L I P链路后,因此,
任何长于2 6 8字节(2 9 6-2 0-8)且“不分片”比特置为1的U D P数据都会使b s d i路由器产生
I C M P“不能分片”差错报文。图11 - 1 3给出了拓扑结构和M T U。
图11-13 使用UDP进行路径MTU发现的系统
可以用下面的命令行来产生6 5 0字节U D P数据报,每两个U D P数据报之间的间隔是5秒:
solaris % sock -u -i -n10 -w650 -p5 slip discard
图11 - 1 4是t c p d u m p的输出结果。在运行这个例子时,将b s d i设置成在I C M P“不能分片”
差错中,不返回下一跳M T U信息。
在发送的第一个数据报中将D F比特置1(第1行),其结果是从b s d i路由器发回我们可以
猜测的结果(第2行)。令人不解的是,发送一个D F比特置1的数据报(第3行),其结果是同
样的I C M P差错(第4行)。我们预计这个数据报在发送时应该将D F比特置0。
第5行结果显示, I P已经知道了发往该目的地址的数据报不能将D F比特置1,因此, I P进
而将数据报在源站主机上进行分片。这与前面的例子中, I P发送经过U D P的数据报,允许具
有较小M T U的路由器(在本例中是b s d i)对它进行分片的情况不一样。由于I C M P“不能分
片”报文并没有指出下一跳的M T U,因此,看来I P猜测M T U为5 7 6就行了。第一次分片(第5
行)包含5 4 4字节的U D P数据、8字节U D P首部以及2 0字节I P首部,因此,总I P数据报长度是
5 7 2字节。第2次分片(第6行)包含剩余的1 0 6字节U D P数据和2 0字节I P首部。
不幸的是,第7行的下一个数据报将其D F比特置1,因此b s d i将它丢弃并返回I C M P差错。
这时发生了I P定时器超时,通知I P查看是不是因为路径M T U增大了而将D F比特再一次置1。
我们可以从第1 9行和2 0行看出这个结果。将第7行与1 9行进行比较,可以看出I P每过3 0秒就将
D F比特置1,以查看路径M T U是否增大了。
这个3 0秒的定时器值看来太短。R F C 11 9 1建议其值取1 0分钟。可以通过修改
i p i r e p a t h m t u i n t e r v a l(E . 4节)参数来改变该值。同时,Solaris 2.2无法对单个
116使用TCP/IP详解,卷1:协议
下载
在这里运行tcpdump命令
将DF比特置1的650字节UDP数据报
ICMP不能分片差错
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
U D P应用或所有U D P应用关闭该路径M T U发现。只能通过修改i p p a t h m t u d i s c o v e r y
参数,在系统一级开放或关闭它。正如在这个例子里所能看到的那样,如果允许路径M T U
发现,那么当U D P应用程序写入可能被分片数据报时,该数据报将被丢弃。
图11-14 使用UDP路径MTU发现
s o l a r i s的I P层所假设的最大数据报长度( 5 7 6字节)是不正确的。在图11 - 1 3中,我们
看到,实际的M T U值是2 9 6字节。这意味着经s o l a r i s分片的数据报还将被b s d i分片。图
11 - 1 5给出了在目的主机( s l i p)上所收集到的t c p d u m p对于第一个到达数据报的输出结果
(图11 - 1 4的第5行和第6行)。
图11-15 从solaris到达slip的第一个数据报
在本例中,s o l a r i s不应该对外出数据报分片,它应该将D F比特置0,让具有最小M T U
的路由器来完成分片工作。
现在我们运行同一个例子,只是对路由器b s d i进行修改使其在I C M P“不能分片”差错
中返回下一跳M T U。图11 - 1 6给出了t c p d u m p输出结果的前6行。
与图11 - 1 4一样,前两个数据报同样是将D F比特置1后发送出去的。但是在知道了下一跳
M T U后,只产生了3个数据报片,而图11 - 1 5中的b s d i路由器则产生了4个数据报片。
第11章UDP:用户数据报协议使用117 下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
图11-16 使用UDP的路径MTU发现
11.9 UDP和ARP之间的交互作用
使用U D P,可以看到U D P与A R P典型实现之间的有趣的(而常常未被人提及)交互作用。
我们用s o c k程序来产生一个包含8 1 9 2字节数据的U D P数据报。预测这将会在以太网上产
生6个数据报片(见习题11 . 3)。同时也确保在运行该程序前, A R P缓存是清空的,这样,在
发送第一个数据报片前必须交换A R P请求和应答。
bsdi % arp -a 验证A R P高速缓存是空的
bsdi % sock -u -i -nl -w8192 svr4 discard
预计在发送第一个数据报片前会先发送一个A R P请求。I P还会产生5个数据报片,这样就
提出了我们必须用t c p d u m p来回答的两个问题:在接收到A R P回答前,其余数据报片是否已
经做好了发送准备?如果是这样,那么在A R P等待应答时,它会如何处理发往给定目的的多
个报文?图11 - 1 7给出了t c p d u m p的输出结果。
图11-17 在以太网上发送8192字节UDP数据报时的报文交换
在这个输出结果中有一些令人吃惊的结果。首先,在第一个A R P应答返回以前,总共产
生了6个A R P请求。我们认为其原因是I P很快地产生了6个数据报片,而每个数据报片都引发
了一个A R P请求。
第二,在接收到第一个A R P应答时(第7行),只发送最后一个数据报片(第9行)!看来
似乎将前5个数据报片全都丢弃了。实际上,这是A R P的正常操作。在大多数的实现中,在等
待一个A R P应答时,只将最后一个报文发送给特定目的主机。
Host Requirements RFC要求实现中必须防止这种类型的A R P洪泛(ARP flooding,
118使用TCP/IP详解,卷1:协议
下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
即以高速率重复发送到同一个I P地址的A R P请求)。建议最高速率是每秒一次。而这里
却在4.3 ms内发出了6个ARP请求。
Host Requirements RFC规定,ARP应该保留至少一个报文,而这个报文必须是最后
一个报文。这正是我们在这里所看到的结果。
另一个无法解释的不正常的现象是, s v r 4发回7个,而不是6个A R P应答。
最后要指出的是,在最后一个A R P应答返回后,继续运行t c p d u m p程序5分钟,以看看
s v r 4是否会返回I C M P“组装超时”差错。并没有发送I C M P差错(我们在图8 - 2中给出了该
消息的格式。c o d e字段为1表示在重新组装数据报时发生了超时)。
在第一个数据报片出现时, I P层必须启动一个定时器。这里“第一个”表示给定数据报
的第一个到达数据报片,而不是第一个数据报片(数据报片偏移为0)。正常的定时器值为3 0
或6 0秒。如果定时器超时而该数据报的所有数据报片未能全部到达,那么将这些数据报片丢
弃。如果不这么做,那些永远不会到达的数据报片(正如我们在本例中所看到的那样)迟早
会引起接收端缓存满。
这里我们没看到I C M P消息的原因有两个。首先,大多数从B e r k e l e y派生的实现从不产生
该差错!这些实现会设置定时器,也会在定时器溢出时将数据报片丢弃,但是不生成I C M P差
错。第二,并未接收到包含U D P首部的偏移量为0的第一个数据报片(这是被A R P所丢弃的5
个报文的第1个)。除非接收到第一个数据报片,否则并不要求任何实现产生I C M P差错。其原
因是因为没有运输层首部,I C M P差错的接收者无法区分出是哪个进程所发送的数据报被丢弃。
这里假设上层(T C P或使用U D P的应用程序)最终会超时并重传。
在本节中,我们使用I P数据报片来查看U D P与A R P之间的交互作用。如果发送端迅速发
送多个U D P数据报,也可以看到这个交互过程。我们选择采用分片的方法,是因为I P可以生
成报文的速度,比一个用户进程生成多个数据报的速度更快。
尽管本例看来不太可能,但它确实经常发生。N F S发送的U D P数据报长度超过8 1 9 2字节。
在以太网上,这些数据报以我们所指出的方式进行分片,如果适当的A R P缓存入口发生超时,
那么就可以看到这里所显示的现象。N F S将超时并重传,但是由于A R P的有限队列,第一个I P
数据报仍可能被丢弃。
11.10 最大UDP数据报长度
理论上,I P数据报的最大长度是6 5 5 3 5字节,这是由I P首部(图3 - 1)1 6比特总长度字段所
限制的。去除2 0字节的I P首部和8个字节的U D P首部, U D P数据报中用户数据的最长长度为
6 5 5 0 7字节。但是,大多数实现所提供的长度比这个最大值小。
我们将遇到两个限制因素。第一,应用程序可能会受到其程序接口的限制。socket API提
供了一个可供应用程序调用的函数,以设置接收和发送缓存的长度。对于UDP socket,这个
长度与应用程序可以读写的最大U D P数据报的长度直接相关。现在的大部分系统都默认提供
了可读写大于8 1 9 2字节的U D P数据报(使用这个默认值是因为8 1 9 2是N F S读写用户数据数的
默认值)。
第二个限制来自于T C P / I P的内核实现。可能存在一些实现特性(或差错),使I P数据报长
度小于6 5 5 3 5字节。
作者使用s o c k程序对不同U D P数据报长度进行了试验。在SunOS 4.1.3下使用环回
第11章UDP:用户数据报协议使用119 下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
接口的最大I P数据报长度是3 2 7 6 7字节。比它大的值都会发生差错。但是从B S D / 3 8 6到
SunOS 4.1.3的情况下,S u n所能接收到最大I P数据报长度为3 2 7 8 6字节(即3 2 7 5 8字节用
户数据)。在Solaris 2.2下使用环回接口,最大可收发I P数据报长度为6 5 5 3 5字节。从
Solaris 2.2到AIX 3.2.2,发送的最大IP数据报长度可以是65535字节。很显然,这个限制
与源端和目的端的实现有关。
我们在3 . 2节中提过,要求主机必须能够接收最短为5 7 6字节的I P数据报。在许多U D P应用
程序的设计中,其应用程序数据被限制成5 1 2字节或更小,因此比这个限制值小。例如,我们
在1 0 . 4节中看到,路径信息协议总是发送每份数据报小于5 1 2字节的数据。我们还会在其他
U D P应用程序如D N S(第1 4章)、T F T P(第1 5章)、B O O T P(第1 6章)以及S N M P(第2 5章)
中遇到这个限制。
数据报截断
由于I P能够发送或接收特定长度的数据报并不意味着接收应用程序可以读取该长度的数
据。因此, U D P编程接口允许应用程序指定每次返回的最大字节数。如果接收到的数据报长
度大于应用程序所能处理的长度,那么会发生什么情况呢?
不幸的是,该问题的答案取决于编程接口和实现。
典型的B e r k e l e y版socket API对数据报进行截断,并丢弃任何多余的数据。应用程
序何时能够知道,则与版本有关(4.3BSD Reno及其后的版本可以通知应用程序数据报
被截断)。
S V R 4下的socket API(包括Solaris 2.x) 并不截断数据报。超出部分数据在后面的读
取中返回。它也不通知应用程序从单个UDP数据报中多次进行读取操作。
TLI API不丢弃数据。相反,它返回一个标志表明可以获得更多的数据,而应用程
序后面的读操作将返回数据报的其余部分。
在讨论T C P时,我们发现它为应用程序提供连续的字节流,而没有任何信息边界。T C P以
应用程序读操作时所要求的长度来传送数据,因此,在这个接口下,不会发生数据丢失。
11.11 ICMP源站抑制差错
我们同样也可以使用U D P产生I C M P“源站抑制(source quench)”差错。当一个系统(路
由器或主机)接收数据报的速度比其处理速度快时,可能产生这个差错。注意限定词“可能”。
即使一个系统已经没有缓存并丢弃数据报,也不要求它一定要发送源站抑制报文。
图11 - 1 8给出了I C M P源站抑制差错报文的格式。有一个很好的方案可以在我们的测试网
络里产生该差错报文。可以从b s d i通过必须经过拨号S L I P链路的以太网,将数据报发送给路
由器s u n。由于S L I P链路的速度大约只有以太网的千分之一,因此,我们很容易就可以使其缓
存用完。下面的命令行从主机b s d i通过路由器s u n发送1 0 0个1 0 2 4字节长数据报给s o l a r i s。
我们将数据报发送给标准的丢弃服务,这样,这些数据报将被忽略:
bsdi % sock -u -i -w1024 -n100 solaris discard
图11 - 1 9给出了与此命令行相对应的t c p d u m p输出结果
在这个输出结果中,删除了很多行,这只是一个模型。接收前2 6个数据报时未发生差
120使用TCP/IP详解,卷1:协议
下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
错;我们只给出了第一个数据报的结果。然而,从第2 7个数据报开始,每发送一份数据报,
就会接收到一份源站抑制差错报文。总共有26 +(7 4×2)= 1 7 4行输出结果。
图11-18 ICMP源站抑制差错报文格式
图11-19 来自路由器s u n 的ICMP源站抑制
从2 . 1 0节的并行线吞吐率计算结果可以知道,以9600 b/s速率传送1 0 2 4字节数据报只需要
1秒时间(由于从s u n到n e t b的S L I P链路的M T U为5 5 2字节,因此在我们的例子中, 20 + 8 +
1 0 2 4字节数据报将进行分片,因此,其时间会稍长一些)。但是我们可以从图11 - 1 9的时间中
看出, s u n路由器在不到1秒时间内就处理完所有的1 0 0个数据报,而这时,第一份数据报还
未通过S L I P链路。因此我们用完其缓存就不足不奇了。
尽管RFC 1009 [Braden and Postel 1987] 要求路由器在没有缓存时产生源站抑制差
错报文,但是新的Router Requirements RFC [Almquist 1993] 对此作了修改,提出路由
器不应该产生源站抑制差错报文。由于源站抑制要消耗网络带宽,且对于拥塞来说是
一种无效而不公平的调整,因此现在人们对于源站抑制差错的态度是不支持的。
在本例中,还需要指出的是, s o c k程序要么没有接收到源站抑制差错报文,要么接收到
却将它们忽略了。结果是如果采用U D P协议,那么B S D实现通常忽略其接收到的源站抑制报
文(正如我们在2 1 . 1 0节所讨论的那样, T C P接受源站抑制差错报文,并将放慢在该连接上的
数据传输速度)。其部分原因在于,在接收到源站抑制差错报文时,导致源站抑制的进程可能
已经中止了。实际上,如果使用Unix 的t i m e程序来测定s o c k程序所运行的时间,其结果是它
只运行了大约0 . 5秒时间。但是从图11 - 1 9中可以看到,在发送第一份数据报过后0 . 7 1秒才接收
到一些源站抑制,而此时该进程已经中止。其原因是我们的程序写入了1 0 0个数据报然后中止
了。但是所有的1 0 0个数据报都已发送出去—有一些数据报在输出队列中。
这个例子重申了U D P是一个非可靠的协议,它说明了端到端的流量控制。尽管s o c k程序
成功地将1 0 0个数据报写入其网络,但只有2 6个数据报真正发送到了目的端。其他7 4个数据报
第11章UDP:用户数据报协议使用121 下载
类型(4) 代码(0) 检验和
8字节
未用(必须为0)
IP首部(包括选项)+原始IP数据报中数据的前8 字节
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
可能被中间路由器丢弃。除非在应用程序中建立一些应答机制,否则发送端并不知道接收端
是否收到了这些数据。
11.12 UDP服务器的设计
使用U D P的一些蕴含对于设计和实现服务器会产生影响。通常,客户端的设计和实现比
服务器端的要容易一些,这就是我们为什么要讨论服务器的设计,而不是讨论客户端的设计
的原因。典型的服务器与操作系统进行交互作用,而且大多数需要同时处理多个客户。
通常一个客户启动后直接与单个服务器通信,然后就结束了。而对于服务器来说,它启
动后处于休眠状态,等待客户请求的到来。对于U D P来说,当客户数据报到达时,服务器苏
醒过来,数据报中可能包含来自客户的某种形式的请求消息。
在这里我们所感兴趣的并不是客户和服务器的编程方面( [Stevens 1990]对这些方面的细
节进行了讨论),而是U D P那些影响使用该协议的服务器的设计和实现方面的协议特性(我们
在1 8 . 11节中对T C P服务器的设计进行了描述)。尽管我们所描述的一些特性取决于所使用
U D P的实现,但对于大多数实现来说,这些特性是公共的。
11.12.1 客户IP地址及端口号
来自客户的是U D P数据报。I P首部包含源端和目的端I P地址, U D P首部包含了源端和目
的端的U D P端口号。当一个应用程序接收到U D P数据报时,操作系统必须告诉它是谁发送了
这份消息,即源I P地址和端口号。
这个特性允许一个交互U D P服务器对多个客户进行处理。给每个发送请求的客户发回应
答。
11.12.2 目的IP地址
一些应用程序需要知道数据报是发送给谁的,即目的I P地址。例如, Host Requirements
R F C规定,T F T P服务器必须忽略接收到的发往广播地址的数据报(我们分别在第1 2章和第1 5
章对广播和T F T P进行描述)。
这要求操作系统从接收到的U D P数据报中将目的I P地址交给应用程序。不幸的是,并非
所有的实现都提供这个功能。
socket API以I P R E C V D S TADDR socket选项提供了这个功能。对于本文中使用的
系统,只有B S D / 3 8 6、4 . 4 B S D和AIX 3.2.2支持该选项。S V R 4、SunOS 4.x和Solaris 2.x
都不支持该选项。
11.12.3 UDP输入队列
我们在1 . 8节中说过,大多数U D P服务器是交互服务器。这意味着,单个服务器进程对单
个U D P端口上(服务器上的名知端口)的所有客户请求进行处理。
通常程序所使用的每个U D P端口都与一个有限大小的输入队列相联系。这意味着,来自
不同客户的差不多同时到达的请求将由U D P自动排队。接收到的U D P数据报以其接收顺序交
给应用程序(在应用程序要求交送下一个数据报时)。
122使用TCP/IP详解,卷1:协议
下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
然而,排队溢出造成内核中的U D P模块丢弃数据报的可能性是存在的。可以进行以下试
验。我们在作为U D P服务器的b s d i主机上运行s o c k程序:
bsdi % sock -s -u -v -E -R256 -P30 6666
from 140.252.13.33, to 140.252.13.63: 1111111111从 s u n 发 送到广播地址
from 140.252.13.34, to 140.252.13.35: 4444444444从4s4 v4 r 4 发 送到单播地址
我们指明以下标志: - s表示作为服务器运行, - u表示U D P,- v表示打印客户的I P地
址,- E表示打印目的I P地址(该系统支持这个功能)。另外,我们将这个端口的U D P接收缓存
设置为2 5 6字节(- R),其每次应用程序读取的大小也是这个数( - r)。标志- P 3 0表示创建
U D P端口后,先暂停3 0秒后再读取第一个数据报。这样,我们就有时间在另两台主机上启动
客户程序,发送一些数据报,以查看接收队列是如何工作的。
服务器一开始工作,处于其3 0秒的暂停时间内,我们就在s u n主机上启动一个客户,并
发送三个数据报:
sun % sock -u -v 140.252.13.63 6666 到以太网广播地址
connected on 140.252.13.33.1252 to 140.252.13.63.6666
1 1 1 1 1 1 1 1 1 1 1 1字节的数据(新行)
2 2 2 2 2 2 2 2 2 1 0字节的数据(新行)
3 3 3 3 3 3 3 3 3 3 3 1 2字节的数据(新行)
目的地址是广播地址( 1 4 0 . 2 5 2 . 1 3 . 6 3)。我们同时也在主机s v r 4上启动第2个客户,并发
送另外三个数据报:
svr4 % sock -u -v bsdi 6666
connected on 0.0.0.0.1042 to 140.252.13.35.6666
4 4 4 4 4 4 4 4 4 4 4 4 4 1 4字节的数据(新行)
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 1 6字节的数据(新行)
6 6 6 6 6 6 6 6 9字节的数据(新行)
首先,我们早些时候在b s d i上所看到的结果表明,应用程序只接收到2个数据报:来自
s u n的第一个全1报文,和来自s v r 4的第一个全4报文。其他4个数据报看来全被丢弃。
图11 - 2 0给出的t c p d u m p输出结果表明,所有6个数据报都发送给了目的主机。两个客户
的数据报以交替顺序键入:第一个来自s u n,然后是来自s v r 4的,以此类推。同时也可以看
出,全部6个数据报大约在1 2秒内发送完毕,也就是在服务器休眠的3 0秒内完成的。
图11-20 两个客户发送UDP数据报的t c p d u m p 输出结果
我们还可以看到,服务器的- E选项使其可以知道每个数据报的目的I P地址。如果需要,
它可以选择如何处理其接收到的第一个数据报,这个数据报的地址是广播地址。
我们可以从本例中看到以下几个要点。首先,应用程序并不知道其输入队列何时溢出。
只是由U D P对超出数据报进行丢弃处理。同时,从t c p d u m p输出结果,我们看到,没有发回
任何信息告诉客户其数据报被丢弃。这里不存在像I C M P源站抑制这样发回发送端的消息。最
后,看来U D P输出队列是F I F O(先进先出)的,而我们在11 . 9节中所看到的A R P输入却是
第11章UDP:用户数据报协议使用123 下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
L I F O(后进先出)的。
11.12.4 限制本地IP地址
大多数U D P服务器在创建U D P端点时都使其本地I P地址具有通配符( w i l d c a r d )的特点。这
就表明进入的U D P数据报如果其目的地为服务器端口,那么在任何本地接口均可接收到它。
例如,我们以端口号7 7 7启动一个U D P服务器:
sun % sock -u -s 7777
然后,用n e t s t a t命令观察端点的状态:
sun % netstat -a -n -f inet
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
udp 0 0 *.7777 *.*
这里,我们删除了许多行,只保留了其中感兴趣的东西。- a选项表示报告所有网络端点
的状态。- n选项表示以点数格式打印I P地址而不用D N S把地址转换成名字,打印数字端口号
而不是服务名称。-f inet选项表示只报告T C P和U D P端点。
本地地址以* . 7 7 7 7格式打印,星号表示任何本地I P地址。
当服务器创建端点时,它可以把其中一个主机本地I P地址包括广播地址指定为端点的本
地I P地址。只有当目的I P地址与指定的地址相匹配时,进入的U D P数据报才能被送到这个端
点。用我们的s o c k程序,如果在端口号之前指定一个I P地址,那么该I P地址就成为该端点的
本地I P地址。例如:
sun % sock -u -s 140.252.1.29 7777
就限制服务器在S L I P接口( 1 4 0 . 2 5 2 . 1 . 2 9 )处接收数据报。n e t s t a t输出结果显示如下:
Proto Recv-Q Send-Q Local Address Foreign Address (state)
udp 0 0 140.252.1.29.7777 *.*
如果我们试图在以太网上的主机b s d i以地址1 4 0 . 2 5 2 . 1 3 . 3 5向该服务器发送一份数据报,
那么将返回一个I C M P端口不可达差错。服务器永远看不到这份数据报。这种情形如图11 - 2 1
所示。
图11-21 服务器本地地址绑定导致拒绝接收UDP数据报
有可能在相同的端口上启动不同的服务器,每个服务器具有不同的本地I P地址。但是,
一般必须告诉系统应用程序重用相同的端口号没有问题。
使用sockets API时,必须指定S O R E U S E A D D R s o c k e t选项。在s o c k程序中是通过-A
选项来完成的。
在主机s u n上,可以在同一个端口号( 8 8 8 8)上启动5个不同的服务器:
124使用TCP/IP详解,卷1:协议
下载
对于SLIP链路
对于以太网
对于环回接口
对于以太网广播
其他(IP地址通配)
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
除了第一个以外,其他的服务器都必须以- A选项启动,告诉系统可以重用同一个端口号。
5个服务器的n e t s t a t输出结果如下所示:
在这种情况下,到达服务器的数据报中,只有带星号的本地I P地址,其目的地址为
1 4 0 . 2 5 2 . 1 . 2 5 5,因为其他4个服务器占用了其他所有可能的I P地址。
如果存在一个含星号的I P地址,那么就隐含了一种优先级关系。如果为端点指定了特定
I P地址,那么在匹配目的地址时始终优先匹配该I P地址。只有在匹配不成功时才使用含星号
的端点。
11.12.5 限制远端IP地址
在前面所有的n e t s t a t输出结果中,远端I P地址和远端端口号都显示为* . *,其意思是该端
点将接受来自任何I P地址和任何端口号的U D P数据报。大多数系统允许U D P端点对远端地址
进行限制。
这说明端点将只能接收特定I P地址和端口号的U D P数据报。s o c k程序用- f选项来指定远
端I P地址和端口号:
sun % sock -u -s -f 140.252.13.35.4444 5555
这样就设置了远端I P地址1 4 0 . 2 5 2 . 1 3 . 3 5(即主机b s d i)和远端端口号4444 。服务器的有名端
口号为5 5 5 5。如果运行n e t s t a t命令,我们发现本地I P地址也被设置了,尽管我们没有指定。
Proto Recv-Q Send-Q Local Address Foreign Address (state)
udp 0 0 140.252.13.33.5555 140.252.13.35.4444
这是在伯克利派生系统中指定远端I P地址和端口号带来的副作用:如果在指定远端地址
时没有选择本地地址,那么将自动选择本地地址。它的值就成为选择到达远端I P地址路由时
将选择的接口I P地址。事实上,在这个例子中, s u n 在以太网上的I P地址与远端地址
1 4 0 . 2 5 2 . 1 3 . 3 3相连。
图11 - 2 2总结了U D P服务器本身可以创建的三类地址绑定。
图11-22 为UDP服务器指定本地和远端IP地址及端口号
在所有情况下,l p o r t指的是服务器有名端口号, l o c a l I P必须是本地接口的I P地址。表中这
三行的排序是U D P模块在判断用哪个端点接收数据报时所采用的顺序。最为确定的地址(第
一行)首先被匹配,最不确定的地址(最后一行I P地址带有两个星号)最后进行匹配。
11.12.6 每个端口有多个接收者
尽管在R F C中没有指明,但大多数的系统在某一时刻只允许一个程序端点与某个本地I P
第11章UDP:用户数据报协议使用125 下载
本地地址远端地址描述
l o c a l I P. l p o r t f o r e i g n I P. f p o r t 只限于一个客户
l o c a l I P. l p o r t * . * 限于到达一个本地接口的数据报: l o c a l I P
* . l p o r t * . * 接收发送到l p o r t的所有数据报
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
地址及U D P端口号相关联。当目的地为该I P地址及端口号的U D P数据报到达主机时,就复制
一份传给该端点。端点的I P地址可以含星号,正如我们前面讨论的那样。
例如,在SunOS 4.1.3中,我们启动一个端口号为9 9 9 9的服务器,本地I P地址含有星号:
sun % sock -u -s 9999
接着,如果启动另一个具有相同本地地址和端口号的服务器,那么它将不运行,尽管我
们指定了- A选项:
sun % sock -u -s 9999 我们预计它会失败
can't bind local address: Address already in use
sun % sock -u -s -A 9999 因此,这次尝试- A参数
can't bind local address: Address already in use
在一个支持多播的系统上(第1 2章),这种情况将发生变化。多个端点可以使用同一个I P
地址和U D P端口号,尽管应用程序通常必须告诉A P I是可行的(如,用- A 标志来指明
S O R E U S E A D D R s o c k e t选项)。
4 . 4 B S D支持多播传送,需要应用程序设置一个不同的s o c k e t选项(S O R E U S E P O R T)
以允许多个端点共享同一个端口。另外,每个端点必须指定这个选项,包括使用该端口
的第一个端点。
当U D P数据报到达的目的I P地址为广播地址或多播地址,而且在目的I P地址和端口号处
有多个端点时,就向每个端点传送一份数据报的复制(端点的本地I P地址可以含有星号,它
可匹配任何目的I P地址)。但是,如果U D P数据报到达的是一个单播地址,那么只向其中一个
端点传送一份数据报的复制。选择哪个端点传送数据取决于各个不同的系统实现。
11.13 小结
U D P是一个简单协议。它的正式规范是RFC 768 [Postel 1980],只包含三页内容。它向用
户进程提供的服务位于I P层之上,包括端口号和可选的检验和。我们用U D P来检查检验和,
并观察分片是如何进行的。
接着,我们讨论了I C M P不可达差错,它是新的路径M T U发现功能中的一部分( 2 . 9节)。
用Tr a c e r o u t e和U D P来观察路径M T U发现过程。还查看了U D P和A R P之间的接口,大多数的
A R P实现在等待A R P应答时只保留最近传送给目的端的数据报。
当系统接收I P数据报的速率超过这些数据报被处理的速率时,系统可能发送I C M P源站抑
制差错报文。使用U D P时很容易产生这样的I C M P差错。
习题
11.1 在11 . 5节中,向U D P数据报中写入1 4 7 3字节用户数据时导致以太网数据报片的发生。在
采用以太网IEEE 802封装格式时,导致分片的最小用户数据长度为多少?
11.2 阅读RFC 791[Postel 1981a],理解为什么除最后一片外,其他片中的数据长度均要求为
8字节的整数倍?
11.3 假定有一个以太网和一份8 1 9 2字节的U D P数据报,那么需要分成多少个数据报片,每个
数据报片的偏移和长度为多少?
11.4 继续前一习题,假定这些数据报片要经过一条M T U为5 5 2的S L I P链路。必须记住每一个
126使用TCP/IP详解,卷1:协议
下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^
数据报片中的数据(除I P首部外)为8字节的整数倍。那么又将分成多少个数据报片?
每个数据报片的偏移和长度为多少?
11.5 一个用U D P发送数据报的应用程序,它把数据报分成4个数据报片。假定第1片和第2片
到达目的端,而第3片和第4片丢失了。应用程序在1 0秒钟后超时重发该U D P数据报,并
且被分成相同的4片(相同的偏移和长度)。假定这一次接收主机重新组装的时间为6 0秒,
那么当重发的第3片和第4片到达目的端时,原先收到的第1片和第2片还没有被丢弃。接
收端能否把这4片数据重新组装成一份I P数据报?
11.6 你是如何知道图11 - 1 5中的片实际上与图11 - 1 4中第5行和第6行相对应?
11.7 主机g e m i n i开机3 3天后,n e t s t a t程序显示48 000 000份I P数据报中由于首部检验和
差错被丢弃1 2 9份,在30 000 000个T C P段中由于T C P检验和差错而被丢弃2 0个。但是,
在大约18 000 000份U D P数据报中,因为U D P检验和差错而被丢弃的数据报一份也没有。
请说明两个方面的原因(提示:参见图11 - 4)。
11.8 在讨论分片时没有提及任何关于I P首部中的选项——它们是否也要被复制到每个数据报
片中,或者只留在第一个数据报片中?我们已经讨论过下面这些I P选项:记录路由
(7 . 3节)、时间戳(7 . 4节)、严格和宽松的源站选路( 8 . 5节)。你希望分片如何处理这些
选项?对照RFC 791检查你的答案。
11.9 在图1 - 8中,我们说U D P数据报是根据目的U D P端口号进行分配的。这正确吗?
第11章UDP:用户数据报协议使用127 下载
该书下载自-书部落-分享计算机经典巨著!--www.shubulo.com!仅供试看^_^

原创粉丝点击