好好回答下 TCP 和 UDP 的区别!
写了这么多篇关于 TCP 和 UDP 的文章,还没有好好聊过这两个协议的区别,这篇文章我们就来开诚布公的谈一谈。
关于 TCP 和 UDP ,想必大家都看过一张这样的图。
有一个小姑娘在对着瓶口慢慢的喝水,下面写着可靠的传输,少女的衣服没有被水浸湿,这张图被称为 TCP 。
然后又有一个小姑娘在举着水瓶以很快的速度向下倒水,少女的头发凌乱,脸色泛红,衣服也被水浸湿,这张图被称为 UDP 。
这两张图我认为是个程序员都能大致总结出来这两个传输协议的不同点(毕竟图上都写的很清楚了)甚至不少同学对 UDP 产生了邪恶的念想,你说作者好好的画个图不行吗,非要在脸上挂个红,把衣服弄湿了才行。。。。。。。
咳,咱们言归正传,TCP 和 UDP 的区别一直是面试的重点,也是经常被用来拿来各种比较的两个协议。
建立连接的差异
TCP 建立连接需要经过三次握手,同时 TCP 断开连接需要经过四次挥手,这也表示 TCP 是一种面向连接的协议,这个连接不是用一条网线或者一个管道把两个通信双方绑在一起,而是建立一条虚拟
通信管道。
TCP 的三次握手流程(客户端向服务器发送建立连接请求):
- 服务端进程准备好接收来自外部的 TCP 连接,一般情况下是调用 bind、listen、socket 三个函数完成。这种打开方式被认为是
被动打开(passive open)
。然后服务端进程处于LISTEN
状态,等待客户端连接请求。 - 客户端通过
connect
发起主动打开(active open)
,向服务器发出连接请求,请求中首部同步位 SYN = 1,同时选择一个初始序号 sequence ,简写 seq = x。SYN 报文段不允许携带数据,只消耗一个序号。此时,客户端进入SYN-SEND
状态。 - 服务器收到客户端连接后,需要确认客户端的报文段。在确认报文段中,把 SYN 和 ACK 位都置为 1 。确认号是 ack = x + 1,同时也为自己选择一个初始序号 seq = y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。此时,TCP 服务器进入
SYN-RECEIVED(同步收到)
状态。 - 客户端在收到服务器发出的响应后,需要给出确认连接。确认连接中的 ACK 置为 1 ,序号为 seq = x + 1,确认号为 ack = y + 1。TCP 规定,这个报文段可以携带数据也可以不携带数据,如果不携带数据,那么下一个数据报文段的序号仍是 seq = x + 1。这时,客户端进入
ESTABLISHED (已连接)
状态。 - 服务器收到客户的确认后,也进入
ESTABLISHED
状态。
而 UDP 是面向数据报的协议,所以 UDP 压根不会有连接的概念,也就不会有三次握手建立连接的过程。
数据传输结束后,通信双方可以释放连接。数据传输结束后的客户端主机和服务端主机都处于 ESTABLISHED 状态,然后进入释放连接的过程。
(客户端主机主动关闭连接)
TCP 断开连接需要历经的过程如下
客户端应用程序发出释放连接的报文段,并停止发送数据,主动关闭 TCP 连接。客户端主机发送释放连接的报文段,报文段中首部 FIN 位置为 1 ,不包含数据,序列号位 seq = u,此时客户端主机进入
FIN-WAIT-1(终止等待 1)
阶段。服务器主机接受到客户端发出的报文段后,即发出确认应答报文,确认应答报文中 ACK = 1,生成自己的序号位 seq = v,ack = u + 1,然后服务器主机就进入
CLOSE-WAIT(关闭等待)
状态,这个时候客户端主机 -> 服务器主机这条方向的连接就释放了,客户端主机没有数据需要发送,此时服务器主机是一种半连接的状态,但是服务器主机仍然可以发送数据。客户端主机收到服务端主机的确认应答后,即进入
FIN-WAIT-2(终止等待2)
的状态。等待客户端发出连接释放的报文段。当服务器主机没有数据发送后,应用进程就会通知 TCP 释放连接。这时服务端主机会发出断开连接的报文段,报文段中 ACK = 1,序列号 seq = w,因为在这之间可能已经发送了一些数据,所以 seq 不一定等于 v + 1。ack = u + 1,在发送完断开请求的报文后,服务端主机就进入了
LAST-ACK(最后确认)
的阶段。客户端收到服务端的断开连接请求后,客户端需要作出响应,客户端发出断开连接的报文段,在报文段中,ACK = 1, 序列号 seq = u + 1,因为客户端从连接开始断开后就没有再发送数据,ack = w + 1,然后进入到
TIME-WAIT(时间等待)
状态,请注意,这个时候 TCP 连接还没有释放。必须经过时间等待的设置,也就是2MSL
后,客户端才会进入CLOSED
状态,时间 MSL 叫做最长报文段寿命(Maximum Segment Lifetime)
。服务端主要收到了客户端的断开连接确认后,就会进入 CLOSED 状态。因为服务端结束 TCP 连接时间要比客户端早,而整个连接断开过程需要发送四个报文段,因此释放连接的过程也被称为四次挥手。
UDP 不存在这条连接,所以它也不需要四次挥手操作。
所以总结一点:TCP 是面向连接的,它的数据传输前需要维护一条虚拟连接,数据传输需要在这条虚拟连接上进行,数据传输完毕后需要断开这条连接,而 UDP 传输不是面向连接的,UDP 发送数据不会建立连接,也不会关心接收端的状态。
可靠性的差异
TCP 和 UDP 一个主要拿来作对比的就是可靠性,TCP 是一种可靠性的传输层协议,UDP 是一种不可靠的传输层协议。TCP 的这种可靠性主要由下面这些特征来保证:
通过序列号和应答号实现可靠性
计算机网络主机之间的相互通信非常类似于我们日常生活中两个人之间打电话,这种对话通常是一问一答形式,如果你讲了一句话并没有收到任何回应,你通常需要再说一次来确保对方是否听到,如果对方给你回应了一句话,就说明他已经听到你的讲话了,这就是一个完整的通话流程(抛开建立连接不谈,我们着重点放在建立连接之后)。
"对方给你的响应" 在计算机网络中被称为确认应答(ACK)
,TCP 就是通过 ACK 来实现可靠的数据传输,也就是说,发送方在发出请求之后会等待目标主机的响应
,如果没有收到响应,发送方在经过一段时间后就会重传请求。所以,即使在发送过程中产生丢包,TCP 仍然能够通过重传来实现可靠性。
上面描述的情况属于发送方请求丢失,还有一种情况属于响应丢失,也就是说请求发送到目标主机后,目标主机会回发 ACK 给请求方,这个 ACK 也有可能丢失,如果 ACK 在链路中丢失,一段时间后请求方没有收到目标主机的 ACK ,仍然会选择重传未收到 ACK 的这个请求。
除了消息丢失之外,还存在一种延迟到达的现象,延迟到达指的是发送方发送一个报文段之后,这个报文也许是由于网络抖动或者网络拥堵导致一个报文段迟迟没有到达目标主机,或者目标主机的响应 ACK 迟迟没有到达发送方的现象。这个一段时间判断的标准就是重传时间,一旦过了重传时间发送方会重传报文段,很可能存在重传报文段到达之后,第一次发送的报文段才刚到的情况,这就存在一个问题:目标主机收到了两个相同的报文段。必须选择一个报文段进行丢弃,但是应该选择哪个报文段呢?
可以通过序列号(seq)来实现,序列号是按照顺序给发送数据的每一个字节都标上号码的编号。接收端通过查询 TCP 首部中的序列号和数据的长度,将自己下一步应该接收的序列号作为确认应答返送回去。通过序列号和确认应答号,TCP 能够识别是否已经接收数据,又能够判断是否需要接收,从而实现可靠传输。
如上图所示,请求按照顺序发送的话是 seq = 1 ,这个请求会把第 1 字节到第 n 字节的数据一起发送过去,等待目标主机一次确认每个字节后,再发送 seq = n + 1 的请求,确认完成后再发送 seq = m + 1 的请求,这样能够保证序列号不会重复。
UDP 没有所谓的序列号和确认号,所以不会对数据进行确认,数据丢失后也不会进行重传,所以 UDP 是一种不可靠的协议。
如果使用 TCP 和 UDP 来比喻开发人员:TCP 就是那种凡事都要设计好,没设计不会进行开发的工程师,需要把一切因素考虑在内后再开干!所以非常靠谱
;而 UDP 就是那种上来直接干干干,接到项目需求马上就开干,也不管设计,也不管技术选型,就是干,这种开发人员非常不靠谱
,但是适合快速迭代开发,因为可以马上上手!
有序性差异
我们上面说到,TCP 会对请求分开发送,每次请求所携带的数据都会被目标主机进行确认,目标主机依次确认每个请求后,就会对请求中的数据进行重组,由于请求是由 seq 的,所以 TCP 在重组这些数据时,也会按照顺序进行重组,而 UDP 没有有序性的这种保证。
报文段的差异
TCP 和 UDP 同属于传输层协议,传输层协议传输的数据统称为报文段
,TCP 和 UDP 的报文段的主要差异如下。
UDP 报文段结构
源端口号(Source Port)
:这个字段占据 UDP 报文头的前 16 位,通常包含发送数据报的应用程序所使用的 UDP 端口。接收端的应用程序利用这个字段的值作为发送响应的目的地址。这个字段是可选项,有时不会设置源端口号。没有源端口号就默认为 0 ,通常用于不需要返回消息的通信中。目标端口号(Destination Port)
: 表示接收端端口,字段长为 16 位。长度(Length)
: 该字段占据 16 位,表示 UDP 数据报长度,包含 UDP 报文头和 UDP 数据长度。因为 UDP 报文头长度是 8 个字节,所以这个值最小为 8,最大长度为 2 ^ 16 = 65535 字节。校验和(Checksum)
:UDP 使用校验和来保证数据安全性,UDP 的校验和也提供了差错检测功能,差错检测用于校验报文段从源到目标主机的过程中,数据的完整性是否发生了改变。
TCP 报文段结构
TCP 报文段结构相比 UDP 报文结构多了很多内容。但是前两个 32 比特的字段是一样的。它们是 源端口号
和 目标端口号
。另外,和 UDP 一样,TCP 也包含校验和(checksum field)
,除此之外,TCP 报文段首部还有下面这些
32 比特的
序号字段(sequence number field)
和 32 比特的确认号字段(acknowledgment number field)
。这些字段被 TCP 发送方和接收方用来实现可靠的数据传输。4 比特的
首部字段长度字段(header length field)
,这个字段指示了以 32 比特的字为单位的 TCP 首部长度。TCP 首部的长度是可变的,但是通常情况下,选项字段为空,所以 TCP 首部字段的长度是 20 字节。16 比特的
接受窗口字段(receive window field)
,这个字段用于流量控制。它用于指示接收方能够/愿意接受的字节数量可变的
选项字段(options field)
,这个字段用于发送方和接收方协商最大报文长度,也就是 MSS 时使用6 比特的
标志字段(flag field)
,ACK
标志用于指示确认字段中的值是有效的,这个报文段包括一个对已被成功接收报文段的确认;RST
、SYN
、FIN
标志用于连接的建立和关闭;CWR
和ECE
用于拥塞控制;PSH
标志用于表示立刻将数据交给上层处理;URG
标志用来表示数据中存在需要被上层处理的 紧急 数据。紧急数据最后一个字节由 16 比特的紧急数据指针字段(urgeent data pointer field)
指出。一般情况下,PSH 和 URG 并没有使用。
所以从报文段结构的对比可以看出,TCP 相比 UDP 多了许多 Flags、序号和确认号,这些都属于 TCP 的连接控制。除此之外还有接收窗口,这些属于拥塞控制和流量控制的内容。TCP 的首部开销要比 UDP 大,因为 TCP 首部固定有 20 字节,UDP 首部固定才 8 字节。TCP 和 UDP 都提供了数据校验功能。
效率的差异
TCP 报文段的发送采用的是"一问一答"形式的,每个请求都会被目标主机确认后再发送下一条报文,效率很慢,后来为了解决这个问题,TCP 引入了 窗口
这个概念,即使在往返时间较长、频次很多的情况下,它也能控制网络性能的下降。
我们之前每次请求发送都是以报文段的形式进行的,引入窗口后,每次请求都可以发送多个报文段,也就是说一个窗口可以发送多个报文段。窗口大小就是指无需等待确认应答就可以继续发送报文段的最大值。
在这个窗口机制中,大量使用了 缓冲区
,通过对多个段同时进行确认应答的功能。
如下图所示,发送报文段中高亮部分即是我们提到的窗口,在窗口内,即是没有收到确认应答也可以把请求发送出去。不过,在整个窗口的确认应答没有到达之前,如果部分报文段丢失,那么发送方将仍会重传。为此,发送方需要设置缓存来保留这些需要重传的报文段,直到收到他们的确认应答。
在滑动窗口以外的部分是尚未发送的报文段和已经接受到的报文段,如果报文段已经收到确认则不可进行重发,此时报文段就可以从缓冲区中清除。
在收到确认的情况下,会将窗口滑动到确认应答中确认号的位置,如上图所示,这样可以顺序的将多个段同时发送,用以提高通信性能,这种窗口也叫做 滑动窗口(Sliding window)
。
UDP 发送的报文段不需要确认,也就没有窗口的概念,所以 UDP 传输效率比较高。
使用场景的差异
TCP 和 UDP 在效率、报文段、流量控制、连接管理上均存在差异,由于这些差异导致了应用场景要有不同的选择,由于 TCP 每个包都需要进行确认,因此 TCP 不适合告诉传输数据的场景,像是这种场景使用 UDP 就好了;像是 Ping 和 DNS Lookup,这类型的操作只需要一次简单的请求/返回,不需要建立连接,用 UDP 就足够了。比如 HTTP 协议需要考虑请求响应的可靠性,这种场景应该使用 TCP 协议,但是像 HTTP 3.0 这类应用层协议,从功能性上思考,暂时没有找到太多的优化点,但是想要把网络优化到极致,就会用 UDP 作为底层技术,然后在 UDP 基础上解决可靠性。
计算机网络系列文章
好好回答下 TCP 和 UDP 的区别!的更多相关文章
- 好好回答下 TCP 和 UDP 的区别
写了这么多篇关于 TCP 和 UDP 的文章,还没有好好聊过这两个协议的区别,这篇文章我们就来开诚布公的谈一谈. 关于 TCP 和 UDP ,想必大家都看过一张这样的图. 有一个小姑娘在对着瓶口慢慢的 ...
- TCP和UDP的区别(转)
TCP协议与UDP协议的区别 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信! ...
- 【基础网络】TCP与UDP 的区别
TCP协议与UDP协议的区别 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信! ...
- 【转】TCP/IP协议中TCP和UDP的区别
TCP协议与UDP协议的区别 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信! ...
- 知其所以然~tcp和udp的区别
TCP UDP TCP与UDP基本区别 基于连接与无连接 TCP要求系统资源较多,UDP较少: UDP程序结构较简单 流模式(TCP)与数据报模式(UDP); TCP保证数据正确性,UDP可能丢包 T ...
- 一文搞懂TCP与UDP的区别
摘要:计算机网络基础 引言 网络协议是每个前端工程师都必须要掌握的知识,TCP/IP 中有两个具有代表性的传输层协议,分别是 TCP 和 UDP,本文将介绍下这两者以及它们之间的区别. 一.TCP/I ...
- HTTP、TCP、UDP的区别
TCP.UDP的区别 1.TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接 2.TCP提供可靠的服务.也就是说,通过TCP连接传送的数据,无差错,不丢失,不重 ...
- 【转载】TCP 与 UDP 的区别
原文地址:TCP 与 UDP 的区别 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信 ...
- TCP的三次握手和四次挥手+TCP和UDP的区别
TCP的三次握手: LISTEN:表示服务器端的某个socket处于监听状态,可以接收连接了. SYN_SENT:当客户端SOCKET执行connect连接时,它首先发送syn报文,随即会进入到此状态 ...
- java:网络编程(InetAddress,InetSocketAddress,URL,TCP(Socket与SeverSocket),TCP与UDP的区别)
InerAddress: /**IP地址:在网络上唯一标示一台计算机 * 端口号:标示计算机上不同的应用程序 * java.net.InetAddress类:此类表示互联网协议 (IP) 地址. * ...
随机推荐
- Cesium开发案例整理
weigis近几年越来越被人们所关注,但是二三维开发难度也比普通web要高出许多,不管我们是在在开发或者是学习过程中,往往需要耗费大量的时间去查阅资料,和研究官方案例, 而大多二三维的包(openla ...
- Tomcat处理http请求之源码分析
本文将从请求获取与包装处理.请求传递给Container.Container处理请求流程,这3部分来讲述一次http穿梭之旅. 1 请求包装处理 tomcat组件Connector在启动的时候会监听端 ...
- 【技术积累】Java中的JVM【一】
什么是JVM JVM英文全称为Java Virtual Machine,中文意为Java虚拟机.JVM是一种能够执行Java语言编写的程序的虚拟机器,它首次作为Java语言的一部分,后来又被移植到了许 ...
- Kubernetes 1.27.2集群安装
基础环境 系统Ubuntu 22.04.2 | 主机名称 | IP | | ----- | -------- | | k8s-master | 192.168.198.141 | | k8s-node ...
- 【python基础】函数-模块
函数的优点之一是,使用它们可将代码块与主程序分离.通过给函数指定函数名称,可让主程序容易理解的多.我们还可以更加细化,将函数存储在被称为模块的独立文件中,再将模块导入到主程序中.import关键字作用 ...
- 在命令行按下tab键之后, 发生了生么?
1. 引言 2. complete命令 3. 自定义补全列表 4. 动态补全列表 5. compgen命令 6. 别名的自动补全 7. 补全规则永久生效 8. 自动加载 9. 参考 1. 引言 当我们 ...
- Swift函数调用方式浅析
函数的调用机制 函数的调用机制是在函数调用时通过那种路径走到最终调用函数地址的机制. 在编程语言中,函数的调用机制有三种 1.静态调用:编译期就确定了函数内存地址,执行效率最高,还可以使用编译器优 ...
- Spring-Bean(二)
环境在spring-Bean(一)的配置下 https://www.cnblogs.com/doubleconquer/p/15603706.html 来查看ApplicationContext的执行 ...
- 服务器衡量标准--RASUM
对于一台服务器来讲,服务器的性能设计目标是如何平衡各部分的性能,使整个系统的性能达到最优.如果一台服务器有每秒处理1000个服务请求的能力,但网卡只能接受200个请求,而硬盘只能负担150个,而各种总 ...
- K8S 对象
本页说明了在 Kubernetes API 中是如何表示 Kubernetes 对象的, 以及使用 .yaml 格式的文件表示 Kubernetes 对象. https://kubernetes.io ...