综述
网络层的 IP 协议为主机之间提供了逻辑通信,而 IP 的服务模型是尽力而为提供服务。这就意味着 IP 尽力在主机之间交付报文,但是它并不做任何保证。不确保报文段的交付,不保证报文段的按序交付,也不保证报文段中数据的完整性。所以 IP 是不可靠的服务
而运输层 (TCP 和 UDP) 将两个端系统间的 IP 的交付服务扩展为运行在端系统上的两个进程间的交付服务。而 UDP 仅提供了进程到进程的数据交付和差错检查两种服务,所以 UDP 也是一种不可靠的服务
TCP 和 UDP 的对比
“TCP 是面向连接的,而 UDP 是无连接的”
建立连接指的是,为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态,用这样的数据结构来保证所谓的面向连接的特性。
面向连接的意思是,在互通之前,面向连接的协议会先建立连接,例如 TCP 会进行三次握手,而 UDP 不会。使用 UDP 时,在发送报文之前,发送方和接收方的运输实体之间没有握手,如此 UDP 才被称为是无连接的。
所以 TCP 和 UDP 的不同之处,主要体现在下面几个方面:
- 可靠交付。通过 TCP 传输的数据,无差错、不丢失、不重复、并且按序到达。而 UDP 继承了 IP 包的特性,不保证不丢失,不保证按顺序到达
- 面向对象不同。TCP 是面向字节流的,发送的时候是一个流,没头没尾。而之所以发送的是流,也是 TCP 自己的状态维护做的事情。但是 UDP 继承了 IP 包的特性,是基于数据包的,一个一个地发,一个一个地收
- 拥塞控制。TCP 有自己地拥塞控制机制,当它意识到包丢弃了或者是网络不好了,就会根据情况调整自己地行为,例如降低发送速度。而 UDP 没有拥塞控制,只会根据应用层地指令发包,即便是网络环境差,只要上层有指令发包,就会一直发
- 有无状态。TCP 通过给数据编号,精确地记录了某个数据发送了没有,接收到没有,发送到哪个了,应该接收哪个。而 UDP 则是无状态的,不记录发送的包的信息
UDP 包的结构
UDP 包是无连接的,那么首次发送 UDP 包时,目的端口号如何得知?服务器上的服务,使用的是 1024 以内的周知端口号,例如 DNS 服务器,那么源主机发送 UDP 时在目的端口号处填写 53 即可。(但是总感觉这个原因逻辑性不强)解析 UDP 包之前的动作:接收方收到一个包之后,会先查看目的 MAC 地址和自己的 MAC 地址是否一致。若一致就把 MAC 头部取下来,再把剩下的部分交给 IP 层。IP 层取下 IP 头部之后,若发现目的 IP 地址和自己的 IP 地址相同,然后再查看 IP 头部里的协议类型,发现 IP 数据包的部分是 UDP 协议。于是就开始解析 UDP 包。将 UDP 包解析出来之后,查看头部的目的端口号,然后把里面的数据交给监听这个端口的某个应用处理。
UDP 的特点
- 结构简单。UDP 的头部只有源端口和目的端口,以及报文长度和校验和,除此之外就是数据部分了。如此应用层就可以进行精确的控制
- 它不会建立连接,虽然有端口号,但是监听时,谁都可以传给他数据,他也可以传给任何人数据,甚至可以同时传给多个人数据
- 无连接状态。TCP 需要维护连接状态,包括接收和发送缓存、拥塞控制参数以及序号与确认号的参数。而 UDP 不维护连接状态,也就没有这些参数。所以运行在 UDP 之上的服务器一般都能支持更多的活跃用户
- 首部开销小。UDP 首部只有 8 个字节,而 TCP 有 20 个字节
UDP 应用场景
- 需要资源少,网络情况好的内网;或者是对于丢包不敏感的应用。例如使用 DHCP ,获取 IP 一般都是在内网进行,就算数据包没有到达,因为是内网,所以也无影响。还有 PXE 安装操作系统时,使用 TFTP 下载操作系统也是使用的 UDP,因为此时客户机还没有操作系统,拥有的资源很少,难以维护较为复杂的 TCP
- 不需要进行一对一沟通、建立连接,可以广播的应用。UDP 无连接,所以可以应用在广播或者多播的协议中。上述提到的 DHCP 就是广播
- 需要处理速度快,时延低,可以容忍少数丢包,但是要求即便网络拥塞,也必须发包的时候。UDP 结构简单,处理速度快,不像 TCP 要保证顺序、还需要重传,因为这会增加时延。而且 UDP 没有拥塞控制,即便网络状况不好,也会发包。而 TCP 此时就会降低发送速度,使得原本卡顿的应用变得更加卡顿。
因为 UDP 结构简单,所以可以由应用自己做一些工作,并利用 UDP 速度快低时延、结构简单的特性,进而开发自定义的应用:
网页或 APP 的访问。原先的网页和 APP 都是基于 HTTP 协议的,而 HTTP 协议是基于 TCP 的。建立连接时需要多次交互,就造成了时延较高的情况。此外手机处于移动过程中,TCP 可能会断开连接,进行重连又会增加时延。而且目前的 HTTP 协议,往往采取多个数据通道共享一个连接的情况,这样本来为了加快传输速度,但是 TCP 的严格顺序策略使得哪怕共享通道,前一个不来,后一个和前一个即便没关系,也要等着,时延也会加大
Chrome 中使用的 QUIC 协议,将 UDP 作为支撑运输协议并在 UDP 之上的应用层协议中实现可靠性
流媒体协议。直播协议多使用 RTMP 协议,而这个协议也是基于 TCP 的。TCP 严格保证数据的顺序性对于直播是不合适的,因为老的视频帧丢了其实也就丢了,就算再传过来用户也不在意了,他们要看新的了。如果老是没来就等着,卡顿了,新的也看不了。所以直播,实时性比较比较重要,宁可丢包,也不要卡顿的。当网络不好的时候,TCP 协议会主动降低发送速度,这就使得原本卡顿的视频更加卡顿。实际上,应用层应该马上重传,而不是主动让步
以下是关于视频帧的说明。视频都是由一张一张的图片形成的,快速播放一组图片也就形成了视频,一张图片在视频里叫做一帧。保存视频时,并不是将每一帧都完整保存,而是保存与上一帧的不同之处,从而降低占用的存储空间。理论上,可以只保留视频的第一帧,以后都保存相较于第一帧的变化。但实际中会隔几帧就保存一整个帧,目的是为了防止传输中出现错误。
这个原理相当于保存 [1000, 1001, 1002, 1003, 1004] 这个数组时,若按照 [1000, 1, 1, 1, 1] 的形式保存,1000 以后的项都保存与前一项之间的大小差距,那么将节省很多存储空间
- 实时游戏。游戏对时效性的要求比较高,实时游戏中客户端和服务端要建立长连接,来保证实时传输。维护 TCP 连接需要在内核维护一些数据结构,因而一台机器能够支撑的 TCP 连接数目是有限的,当玩家数量增多之后,一台机器就不够用了。而 UDP 是没有连接的,在异步 IO 机制引入之前,常常是应对海量客户端连接的策略。另外还是 TCP 的强顺序问题,对战游戏中,客户端发送给服务器鼠标和键盘行走的位置,服务器会处理每个用户发送过来的所有场景,处理完再返回给客户端,客户端解析响应,渲染最新的场景展示给玩家。如果出现一个数据包丢失,所有事情都需要停下来等待这个数据包重发。客户端会出现等待接收数据,然而玩家并不关心过期的数据。游戏对实时要求较为严格的情况下,采用自定义的可靠 UDP 协议,自定义重传策略,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成的影响。
- Iot 物联网。一方面,物联网领域终端资源少,很可能只是个内存非常小的嵌入式系统,而维护 TCP 协议代价太大;另一方面,物联网对实时性要求也很高,而 TCP 还是因为上面的那些原因导致时延大
- 移动通信领域。在 4G 网络里,移动流量上网的协议 GTP-U 就是基于 UDP 的。因为移动网络协议比较复杂,而 GTP 协议本身就包含复杂的手机上线下线的通信协议。如果基于 TCP,TCP 的机制就显得非常多余
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。