UDP协议的特点与原理

用户数据报协议(User Datagram Protocol,UDP)是当今互联网传输层的两个主要协议之一,与另一个协议(传输控制协议,TCP)互为补充。其地位十分重要,值得在此介绍。

[RFC0768]是UDP协议的正式规范,它至今仍然是一个标准,30多年来没有做过重大的修改。

对于RFC,感兴趣的大家可以上网查一下,它的全称是“Request For Comments”,即“请求评论”。包含了几乎所有重要的Internet文字资料。一个RFC出版后永远不会被修改或取消,而只有可能被新的RFC取代。这里说UDP“至今仍然是一个标准”,也就是说它从出现至今从未被更新过,可见其设计的简洁与高明。

撰写本文主要想通过介绍UDP协议的特点与原理,看透UDP协议设计背后的思想,深度理解通信、端口和连接等概念。

UDP协议的特点

所谓特点,即与其他协议的不同之处。如前所述,能与UDP比较的协议非TCP莫属,故下文会反复提到TCP协议,如果你没听说过TCP,问题也不大,我会尽量详细介绍其中各个概念。

总而言之,UDP有如下几个特点:

  • 无连接
  • 不可靠
    • 不提供差错纠正、队列管理、重复消除、流量控制和拥塞控制
  • 保留消息边界
  • 开销小、效率高

那么相对应的,TCP的特点如下:

  • 有连接
  • 可靠
  • 不保留消息边界
  • 开销比UDP大

那么一目了然,UDP的特点反过来就是TCP的特点,反之亦然。那么到底什么是无连接?什么不可靠?什么是消息边界呢?别急,我马上就讲~

什么叫无连接?

graph LR
	subgraph Sender
	Sender_IP[192.168.1.101]
	end
	subgraph Receiver
	Receiver_IP[192.168.1.102]
	end
	Sender_IP --> Receiver_IP

我们知道,UDP是一个传输层的协议,它工作在网络层之上,具体来说,工作在IP协议之上。位于网络层的IP协议为我们实现了将数据从网络上一个IP主机发送到另一个主机的功能。而一台主机上可能有多个程序需要同时和其他主机上的程序通信,这个问题则直接砸到了传输层协议的脑袋上。

由于当今互联网几乎全部使用的都是TCP/IP协议,所以当我提到”网络层协议“时,毫无疑问指的就是IP协议或它的升级版ICMP协议;当我提到”传输层协议“时,想介绍的则是UDP协议和TCP协议共通之处。

传输层协议引入一个“端口”的概念用于解决上述问题,每个传输层数据包都会指定要发往哪个“端口”,而对应的应用程序只需预先绑定这个端口,就能正确收到发给它的数据。

graph LR
	subgraph Sender
	Sender_Port1[Port: 10086]
	Sender_Port2[Port: 10087]
	Sender_IP[192.168.1.101]
	end
	subgraph Receiver
	Receiver_Port1[Port: 10000]
	Receiver_Port2[Port: 10001]
	Receiver_IP[192.168.1.102]
	end
	Sender_Port1 --> Receiver_Port1
	Sender_Port2 --> Receiver_Port2

端口一般是一个16位正整数,所以范围一般是0到65535。

不可靠

UDP协议不提供重复消除

说UDP协议不可靠,是因为当你使用它发送数据时,并不能保证你的数据真的能被送到目标机器的目的端口,而是有可能发生丢失或重复。是的,不仅有可能丢失,还有可能重复(即被收到多次)。

反过来也可以说,TCP协议保证你发送的数据会被并且仅仅会被接收到一次。

UDP协议不提供队列管理

何为队列管理?这里的队列管理指的是是否保证消息的顺序

假设你打算用发送5个数据包,他们大小不一,我们依发送次序给它们编号:

0 1 2 3 4
事证实明 文字的 序顺 并不响影 读阅

如果你用UDP协议发送它们,那么接收方接收时的情形会是如何呢?最好的情况下当然是按照原样收到,但也完全可能出现如下情况:

2 1 0 4 3
序顺 文字的 事证实明 读阅 并不响影

可以看到各个数据包之间的顺序被打了,但是单个数据包并没有发生改变。什么是单个数据包没有发生改变?请听下节分解……

保留消息边界

前面说到,UDP的特点是虽然不能保证数据们按照它们被发送的顺序被依次收到,但是可以保证消息的边界不发生改变。为了说明什么是消息边界发生改变,接下来给出一个TCP的例子:

0 1 2 3
事证实 明文 字的序顺并不 响影读阅

可以观察到在TCP中,顺序得到了保证,但是数据包的边界发生了改变。事实上,当你在接收TCP数据时,消息边界完全可以由你自己决定:先读三个字,读到的就是“事证实”,再读四个字,读到的就是“明文字的”。

老师上课举的一个例子非常形象,传输数据就像是运输石油,UDP就相当于用油罐车运输,TCP则相当于管道运输。 如果你用五辆油罐车运输五车石油,最先到的油罐车不一定就是最先出发的那辆,但是每辆车内的石油之间是严格分界的; 如果用管道运输这五份石油,最先进入管道的石油必定最先从出口出来,但是每份石油之间的边界并不存在。

UDP协议原理

数据包格式


 0      7 8     15 16    23 24    31  
+--------+--------+--------+--------+ 
|     Source      |   Destination   | 
|      Port       |      Port       | 
+--------+--------+--------+--------+ 
|                 |                 | 
|     Length      |    Checksum     | 
+--------+--------+--------+--------+ 
|                                     
|          data octets ...            
+---------------- ...                 

     User Datagram Header Format

 0      7 8     15 16    23 24    31 
+--------+--------+--------+--------+
|          source address           |
+--------+--------+--------+--------+
|        destination address        |
+--------+--------+--------+--------+
|  zero  |protocol|   UDP length    |
+--------+--------+--------+--------+

            Pseudo Header

我能发送无限长的数据吗?

不能,懒得算最大报文长度了,读者自己算下吧。

什么是端口号?

此处想解释tcp的端口跟udp端口的关系,它们会冲突吗?如果udp把端口号定义为32字节,tcp会受到影响吗?

重新理解“连接”

这里想解释连接的概念,udp协议定义的源端口号和目的端口号能否看成一个最原始的连接呢?

总结

咕?