“DNS经常用UDP,但通用DNS实现也须支持TCP。DNS/TCP在消息前加两字节长度,与本单元的教学分帧相似,却不采用16字节教学上限。传输选择、缓存有效期和递归查询次数,都是总超时预算的…”
形式陈述
UDP在IP之上提供带端口的数据报服务。普通UDP首部为8字节,包含16位源端口、目的端口、长度和校验和;长度包含首部与载荷。接收端以数据报为单位交付,保留一次发送的边界,但不承诺送达、不重复、按发送顺序到达或时延上界。
数据报身份与载荷值不同。应用若连续发送两个相同字节串,它们是两个合法发送;网络再复制其中一个时,接收者不能仅凭“内容一样”判断哪个该删。应用需要重试与去重时,应另设计身份和状态,UDP首部没有提供完整的业务调用编号。
本页选用POSIX式SOCK_DGRAM、recv的flags=0接收合同(不使用MSG_PEEK):一次接收取一份数据报;若所给缓冲过小,超出的部分被丢弃,而不是留给下次接收续读。具体API怎样报告截断、是否可查询原长应按接口核查。零长度UDP数据报也是一份数据报,因此“读到0字节”不能照搬TCP的有序EOF解释。
IPv4 UDP校验和允许特殊的未使用表示;普通IPv6 UDP要求非零校验和,少数受限隧道例外不在本页。校验和检测部分传输错误,既非加密认证,也不能阻止能重算校验和的主动修改。
直觉
UDP像分别投递的一张张便条:边界清楚,但不会替收件人补齐漏掉的便条,也不会替发送者判断对方读过没有。TCP则让应用看到连续字节,交付边界留给应用重新定义。这两种接口各有用途,不存在“UDP只是较差的TCP”的总排序。
没有建连握手不代表一次调用没有状态。有的系统提供UDP connect,用于设定默认对端与过滤等本地行为;它不把底层服务变成可靠字节流。
例子与边界
应用发送带自定义编号的D7=A、D8=BC。网络允许接收顺序D8、D7、D7,也允许只收到D8,或一个都收不到。接收者保存“已见编号”能抑制同一编号的重复,却不能凭只收到D8就证明D7永久丢失。缺口等待策略需要期限与失败口径。
另一条10字节数据报abcdefghij到达,应用只提供4字节缓冲。本页接口最多交付abcd并丢掉其余6字节;下一次接收会面对下一份数据报,不会自动得到efghij。按TCP方式循环“再读到10字节”为止,可能错误拼接两个不同消息。
在IPv4无选项、路径MTU=1500且避免IP分片的条件下,UDP应用载荷至多为
推论与应用
适合UDP的应用通常能解释丢失或自行实现所需的恢复、排序、拥塞响应。增加重传后,发送速率也必须考虑共享网络;“协议首部没有拥塞窗口”不是可以无限重发的许可。
DNS常用UDP,也支持TCP;应用协议的名字与承载协议不是一对一关系。一个可靠应用协议可以以UDP为载体,但其可靠性来自新增状态机与假设,不来自UDP名称本身。