UDP

概述

       用户数据保协议(User Datagram Protocol,UDP)是开放系统互联模型(Open System Interconnection,OSI)中传输层协议的一种,是一种保留消息边界的简单的面向数据报的协议。UDP不提供差错纠正、队列管理、重复消除、流量控制和拥塞控制,但提供差错检测(包含我们在传输层中碰到的第一个真实的端到端(end-to-end)校验和)。这种协议自身提供最小功能,因此使用它的应用程序要做许多关于数据报如何发送和处理的控制工作。想要保证数据被可靠传递或正确排序,应用程序必须自己实现这些保护功能。一般来说,每个被应用程序请求的UDP输出操作只产生一个UDP数据报,从而发送一个IP数据报。而对于面向数据流的传输层协议(例如TCP),应用程序写入的全部数据与真正在单个IP数据报里传送的或接收方接收的内容可能没有联系。

        UDP把数据报发送出去,但并不保证它们能够到达目的地。另外,没有协议机制防止告诉UDP流量对其他网络用户的消极影响。这种可靠性和保护性的缺失需要上层协议来代替UDP完成,但因为UDP的无连接特性,它要比其他传输协议使用更少的开销。另外,广播和组播更多直接使用像UDP这样的无连接传输。最后,应用程序可选择自己的重传单元的能力(因为上层协议可以自主决定要提供多大的可靠性)是一项重要的考虑。

《UDP》

UDP校验和

       UDP校验和覆盖了UDP头部、UDP数据和一个伪头部。它由初始的发送方计算得到,由最终的接收方校验。它在传送中不会被修改(除非通过NAT)。传输层协议(如TCP、UDP)使用校验和来覆盖它们的头部和数据。对于UDP来说,校验和是可选的(尽管强烈推荐使用),而其他的则是强制的。当UDP在IPv6中使用时,校验和的计算和使用时强制的,因为在IP层没有头部校验和。为了给应用程序提供无差错数据,像UDP这样的传输层协议,在投递数据到接收方应用程序之前,必须计算校验和或者使用其他差错检测机制。

《UDP》

       UDP校验和的计算方法与普通互联网校验和(Internet checksum)类似,但要注意两点。首先,UDP数据报长度可以使奇数个字节,而校验和算法只相加16位字(总是偶数个字节)。UDP的处理过程是在奇数长度的数据报尾部追加一个值为0的填充(虚)字节,这仅仅是为了校验和的计算与验证,实际上填充字节不会被传送出去,因此是虚的。

       第二点是UDP(也包括TCP)计算校验和时包含了衍生自IPv4头部的一个12字节的伪头部(如上图所示)或衍生自IPv6头部字段的一个40字节的伪头部。这个伪头部也是虚的,仅用于校验和的计算与验证,不会被传送出去。这个伪头部包含了来自IP头部的源IP地址和目的IP地址以及协议或下一个头部字段(值应该是17)。它的目的是让UDP验证数据是否已经到达正确的目的地。对于伪头部的操作违反了互联网协议的分层规则(UDP作为传输层协议直接操作网络层的数据),但这只产生微小的影响(不像NAT),因为一般来说,当数据传送到(或来自于)UDP时,网络层(IP)数据已经是现成的了,UDP不过是将其作为检验的一部分而已,不会修改。

       UDP数据报校验和虽然在原始UDP规范中是可选的,但它们还是被要求在主机中默认使用。因为当数据通过路由器时,总会存在有软件和硬件漏洞的路由器在转发数据报时会修改其中的数据。如果校验和被关闭,这些错误就无法被检测到。而在IPv6中,IP层的头部校验和时不存在的,因此传输层的校验和是必须的。

UDP-Lite

       有些应用程序可以容忍在发送和接收数据里引入的比特差错。通常,为了避免建立连接的开销或为了使用广播或组播地址,这类应用程序都会选择使用UDP,但是UDP使用的校验和要么覆盖整个负载,要么就干脆没有校验和。一个称为UDP-Lite的协议通过修改传统的UDP协议,提供了部分校验和来解决这个问题。这些校验和可以只覆盖UDP数据报里的一部分负载。UDP-Lite有它自己的IPv4协议和IPv6下一个头部字段,因此它实际上算是一种独立的传输层协议。UDP-Lite用一个校验和覆盖范围(Checksum Coverage)字段代替了冗余的长度字段来修改传统UDP头部。如下图:

《UDP》

       校验和覆盖字段是被校验和覆盖的字节数(从UDP-Lite头部的第1个字节开始)。除了特殊的值以外,最小值是8,因为UDP-Lite头部自身总是要求被校验和覆盖。值0表示整个负载都被校验和覆盖,这就和传统UDP一样了。而对于IPv6超长数据报,因为用于存放校验和覆盖范围字段的空间有限(只有16位),对于这类数据报,被覆盖范围最多可以是64KB或整个数据报(值为0即全覆盖)。

最大UDP数据报长度

       理论上,一个IPv4数据报的最大长度是65535字节,这由IPv4头部的16位总长度字段决定。除去20字节不带选项的IPv4头部和一个8字节的UDP头部,就剩下最大65507字节留个UDP数据报的数据部分。而对于IPv6,假设没有使用超长数据报,16位负载长度字段可允许655535字节的UDP数据报长度(除去8字节被用于UDP头部后只剩下655527字节)。虽然理论上可以达到这些数值,但这些大小满额的数据报多数不能被端到端投递。因为可能系统本地协议实现有一些限制(可通过API套接字修改能处理的最大数据报长度),还有可能是应用程序没法处理这么大的数据报。

数据报截断

       UDP/IP能发送和接收一个指定大小的数据报并不意味着接收数据报的应用程序能够读取这种大小的数据报。UDP编程接口允许应用程序指定每次读操作完成时返回的最大字节数。如果接收的数据报超过应用程序的限定值,大多数情况下会发生API截断(truncate),丢弃这个数据报里超过接收应用程序指定字节数的任何超额数据。但所谓“丢弃”,每种实现的具体操作是不同的,一些系统把这些超额数据放到下一次读操作中,另一些则通知调用者多少数据被截断了(或只报告有数据截断)。

流量和拥塞控制的缺失

       大多数UDP服务器是迭代(iterative)服务器,即单个服务器线程(或进程)在单个UDP端口处理所有客户请求。通常一个应用程序使用的每个UDP端口均有一个大小有限的队列与之对应。也就是说来自不同客户机多个请求会被UDP自动排入队列里以一定策略排序(最简单的实现是FCFS,先来先服务),接收到的UDP数据报中排在最前的一个先被传送给应用程序。

       然而,这个队列有可能会溢出,使得UDP丢弃进入的数据报。因为UDP不提供流量控制(flow control),也就是说服务器无法让客户机减慢速率。因为UDP是一个无连接协议,自身没有可靠机制,应用程序无法得知什么时候UDP输入队列产生了溢出,超额的数据报仅仅是被丢弃而已。

       当网络节点(比如路由器)中发生类似的满队列的情况时,就说网络发生了拥塞(congested)。拥塞会影响所有流量经过拥塞发生地点的网络用户,这与前面提到的UDP输入情况不一样,那里作为端点,只有单个应用程序服务受影响。然而UDP无连接的特性意味着当网络正在拥塞时,不能通知对端降低发送率。

 

                                                                              本文部分内容摘自《TCP/IP详解 卷1:协议(中文版)第2版》

    原文作者:___Blue_H
    原文地址: https://blog.csdn.net/qq_37653144/article/details/81636040
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞