最近开始在恶补网络知识,算是一个复习,在学习了很多上层建筑之后回来看看之前的基础确实又有一个新的认识。一开始准备看完之后做一个整体的总结,但是发现知识点太多所以分了几期来写,每期都会短一点,这期我们先来简单了解一下 UDP

前言

传输层中重要的两个协议 UDP 和 TCP ,在平时的时候,你虽然一直用着他们,但是往往感受不到他们的存在,他们两个往往经常会在面试的时候出现,打你一个措手不及。

在学习它之前,你首先要有一个概念,为什么我们需要 UDP 或者 TCP 这样的协议,它到底是在什么时候,什么地方,帮我们完成了什么样的事情?

  • 在网络,我们研究的往往都是如何以一种合理的方式传递数据

而且协议则指定了这样的规定,当双方都遵守这样的规定,才能看懂互相说的话,才能达到合理传递数据的目的。

UDP 怎么样

  • UDP 格式简单,没有花里胡哨的东西
  • UDP 不会先探路,而是直接就发上了
  • UDP 不会管你卡不卡,发给你我就不管了

报文格式

源端口号(16 位,2 字节) 目的端口(16 位,2 字节)
UDP 长度(16 位,2 字节) UDP 校验和(16 位,2 字节)
数据 数据

我们可以看到,UDP 的报文真的是很简单,除了简单的对于数据做了校验,就是必要的端口号,没了。

UDP 对比 TCP

其实这两者区别巨大,但是你要明白的是为什么会有这样的区别。

连接

如果有人问,TCP 和 UDP 的区别? 很多时候会得到的第一个答案就是告诉你,TCP 是面向连接的,而 UDP 是面向无连接的。那么问题来了,是说 UDP 不需要网络连接吗?那 UDP 的包不通过网络连接怎么发送的呢?

其实,这里所谓的连接是指,** 客户端和服务端是否有在维护双方通信的状态 **,如果维护了这样的状态,那么对于服务端来说我很清楚现在的局势状况,客户端发了多少数据了,是否需要断开了,是否有丢数据了等等。

可靠

TCP 为什么说它可靠,而 UDP 不可靠呢?

也很简单,你看报文格式就很清楚,UDP 没有做过多的校验,对于 UDP 的包来说,重复了,没收到都是这样的事情出现都是完全不清楚的。

而 TCP 就可靠很多了,它的报文格式恐怕要你背,你可能就要想想了吧,它需要很多东西去控制,去保证有序、无差错、不丢失、不重复。

字节流 和 数据报

TCP 是面向字节流的,发送的时候一个流就过来了,而 UDP 是数据报的,一个个来的

拥塞控制

这个也很好理解,TCP 因为他知道的多,他很清楚当前局势,网络状况,从而会主动控制发送的频率,而 UDP 它啥也不知道,没办法控制发送频率,它都不知道别人收到了没有,只管发就完事了。

应用场景

那么 UDP 那么不靠谱,那什么情况下会用到这个协议呢?之前都一直在说 UDP 和 TCP 比有什么不好的地方,但是它有着别人无法相比的优点,那就是快。

内网环境

很多时候在内网环境,网络条件是很好的,又能两个设备之间就经过了一个路由器而已,相比于互联网中纷繁复杂的世界,这个时候丢包的可能性就很小了。那么这个时候为了速度,使用 UDP 就是很好的选择

  • DHCP 动态主机配置协议,在分配 IP 地址的时候显然肯定是内网,用 UDP 再好不过了
  • TFTP 简单文件传输协议,当使用 PXE 方式安装操作系统时,当 DHCP 返回 PXE 服务器地址,然后要做的就是下载镜像了,而镜像一般都挺大的,而这个时候使用 UDP 很合适
  • SNMP 简单网络管理协议,用它可以管理网络中的很多设备,获取这些设备的状态,当然这些网络设备都是在内网的一个安全环境下

速度 & 实时性

很多时候我们对于速度和实时性有要求,而又对丢失一两个数据并不在意的时候就会用到 UDP,你可能会好奇有这样的场景吗?有的

  • 直播,如果丢了其中某一帧的画面并不影响用户整体观看,而如果我非要等到这一帧的数据重传给我,那肯定就卡了。
  • FPS 游戏,对于实时性要求要的游戏,很多时候都会在协议上好好的做文章,因为会非常影响用户体验,同样的,如果中间有数据丢了,不能等着这个数据重发给我,否则等数据回来早就被别人打死了。

扩展

因为 UDP 几乎什么都没有,所以它就能被改成你想要的样子,如果你觉得当前可靠性不够,你可以自己在上层继续实现如:重传、拥塞控制等功能来扩展。

  • QUIC 快速 UDP 互联网连接,google 提出的使用 UDP 进行多路并发传输的协议,基于 UDP 的一个协议,有 TLS,有 HTTP2,利用缓存减少连接时间等等

不只是 UDP

当然应用层的其实有的协议并不只是使用简单的一个 UDP 或者 TCP 来实现,有的时候两者都会使用

Socket

这个是我们最常见的在应用层的一个协议了,我们知道在使用的时候可以通过指定参数来确实使用 UDP 或者 TCP 都可以。

int socket (int domain, int type, int protocol);

  • 其中 domain 表示 IP 层使用什么协议是 IPv4 还是 IPv6

  • type 表示 socket 类型,SOCK_STREAM 表示 TCP 面向流,SOCK_DGRAM 就是 UDP 面向数据报的,SOCK_RAW 直接操作 IP 层或者其他协议如 ICMP

  • protocol 表示的协议,IPPROTO_TCP 或者 IPPTOTO_UDP

DNS

当我们想通过一个域名访问一个网站时,第一步操作就是去找这个域名所对应的 IP 地址,而 DNS 就是这个功能。

绝大多数情况下,DNS 服务都是用的 UDP 来做的,因为快嘛,而且本身传递的消息也不多。

但是,因为 DNS 服务器之间是需要进行数据的一个同步或者迁移操作的,辅助 DNS 服务器会定时向主域名服务器同步变动,叫做区域传送,而这个时候数据量是有可能很大的,而且为了确保信息不丢失,使用 TCP 来保证才是一个不错的选择。

总结

总的来说,UDP 还是非常简单的一个协议,没有过多的约束,从而在一些特定的情况下满足用户的需求。这里也体现了 trade-off ,速度还是可靠,要安全还是要性能,往往都是在权衡,也往往需要针对场景去选择。