# 5.2 UDP协议

## 5.2.1 UDP数据报

### 1、UDP概述

UDP只在IP数据报服务之上增加了很少功能，即复用分用和差错检测功能。

#### UDP的主要特点

* UDP是<mark style="color:orange;">**无连接**</mark>的
* UDP<mark style="color:orange;">**不保证可靠交付**</mark>
* UDP是<mark style="color:orange;">**面向报文**</mark>的，适合一次性传输少量数据的网络应用
* UDP无拥塞控制，适合很多实时应用
* UDP首部开销小

{% hint style="success" %}
**面向报文**：应用层给UDP多长的报文，UDP就照样发送，即一次发一个完整报文，不做处理

<img src="https://1628974532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKXaHhVFQadnoaaLPklBX%2Fuploads%2Fgit-blob-98537858ec8eee864dc23a64d984f227ede07c34%2F%E9%9D%A2%E5%90%91%E6%8A%A5%E6%96%87.png?alt=media" alt="面向报文" data-size="original">
{% endhint %}

### 2、UDP首部格式

![UDP首部格式](https://1628974532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKXaHhVFQadnoaaLPklBX%2Fuploads%2Fgit-blob-3ec0c4fcb133a2a4a48bbb75bebd108cbc299185%2FUDP%E9%A6%96%E9%83%A8%E6%A0%BC%E5%BC%8F.png?alt=media)

* **首部字段**
  * **源端口号**（16位，2B）：可选填，当需要目的主机回应时使用
  * **目的端口号**（16位，2B）：<mark style="color:orange;">**必要**</mark>，目的进程的端口号
  * **UDP长度**（16位，2B）：整个UDP数据报的长度（首部字段+数据字段）
  * **UDP检验和**（16位，2B）：检测<mark style="color:orange;">**整个**</mark>UDP数据报是否有错误
* **数据字段**

{% hint style="warning" %}
分用时，找不到对应的目的端口号，就丢弃报文，并给发送方发送ICMP“端口不可达”差错报告报文
{% endhint %}

## 5.2.2 UDP校验

### 1、伪首部

![UDP校验](https://1628974532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKXaHhVFQadnoaaLPklBX%2Fuploads%2Fgit-blob-6315aec064395338f5e7fb17fdbe52156e429e85%2FUDP%E6%A0%A1%E9%AA%8C.png?alt=media)

**伪首部**：只有在<mark style="color:orange;">**计算检验和**</mark>时才出现， 不向下传送也不向上递交

伪首部模仿的是IP数据报的首部：

* **源IP、目的IP**（4B）
* **0**（1B）：固定字段
* **17**（1B）：UDP的协议对应
* **UDP长度**（2B）：UDP首部8B+数据部分长度，<mark style="color:orange;">**不包括伪首部**</mark>

### 2、校验过程

* 若不使用校验，则将校验和字段全部置0

![UDP校验填充](https://1628974532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKXaHhVFQadnoaaLPklBX%2Fuploads%2Fgit-blob-3ecc087641d57a8a52ad35acbe59fa1a3f9731b5%2FUDP%E6%A0%A1%E9%AA%8C%E5%A1%AB%E5%85%85.png?alt=media)

* 发送方
  1. 加上伪首部
  2. 全0填充检验和字段
  3. 全0填充数据部分（使整个UDP数据报是4字节的整数倍）
  4. 将伪首部+首部+数据字段进行<mark style="color:orange;">**二进制反码求和**</mark>
     * 以16bit（2B）为一组分开进行求和（校验和字段长度）
  5. 将求和结果填入检验和字段
     * 若结果恰好全为0，则全部填入1
  6. 去掉伪首部
  7. 发送
* 接收方
  1. 加上伪首部
  2. 将伪首部+首部+数据字段进行<mark style="color:orange;">**二进制反码求和**</mark>
     * 结果全为1，则无差错
     * 否则视情况丢弃数据，或交给应用层并附上差错警告
