1. 前言
TCP 和 UDP 协议是计算机网络的重要组成协议,两者经常被拿来比较,其中 TCP 协议往往会被面试官深入考察。
本节课程将和大家一起学习传输层的 TCP 和 UDP 协议。通过本节课程,你会了解到 TCP 和 UDP 协议的区别,重点是要掌握 TCP 协议的三次握手过程以及三次握手的必要性。
2.1 TCP 和 UDP
面试官提问: TCP 协议和 UDP 协议有什么区别?有什么共同点?
题目解析:
相同点:两个协议最大的共同点是都位于 TCP/IP 网络模型的传输层。
不同点:我们通过表格的形式对比不同。
TCP(Transmission Control Protocol,传输控制协议) | UDP(User Datagram Protocol,用户数据报协议) | |
---|---|---|
是否连接 | 面向连接 | 无连接 |
传输方式 | 面向字节流:直接以字节流形式传输 | 面向报文:对于应用程序交付的数据,添加首部之后就交付给 IP 层 |
首部格式 | 20 个字节的固定首部 | 只有 8 个字节 |
是否可靠 | 可靠传输,依靠流量控制和拥塞控制 | 不可靠传输 |
连接对象个数 | 一对一连接 | 支持一对一(点到点),一对多以及多对多传输 |
适用场景 | 要求可靠传输的场景,例如发送邮件和传输文件 | 对可靠性要求低,效率要求高的场景,例如 QQ 的视频通话 |
根据表格中的特点对比我们可以总结得到:
- TCP 协议面向连接并且可靠,UDP 协议无连接并且不可靠;
- 虽然 UDP 协议不可靠,但是在对数据完整性要求低,对传输速度要求高的场景,可以适用 UDP 协议。
2.2 TCP 和 UDP 报文
面试官提问: 上述你提到了 UDP 和 TCP 报文,它们的具体结构是怎样的?
题目解析:
在上个题目中我们总结了 TCP 协议和 UDP 协议的不同点,其中谈到了 TCP 和 UDP 协议首部格式不同,接下来分别画图分析。
如上图可见,UDP 首部只有 8 个字节的数据,包括源端口号、目标端口号、长度以及校验和。
- 源端口号:发送计算机的应用端口;
- 目标端口号:接收端计算机的接收端口,也是占用 16 位 Bit;
- 长度:表示 UDP 报文首部以及携带数据的长度;
- 校验和:校验数据在传输过程中是否损坏。
在画完了示意图之后,关于 TCP 报文首部,我们需要解释的字段:
-
序号:对字节流编号,例如本次传输的序号是 100,携带的数据长度是 100 字节,那么下次传输的序号就是 200;
-
确认号:客户端 A 往服务器端 B 发送了一个报文,序号是 100,携带的数据长度是 100 字节,那么 B 往 A 发送的报文中确认号就是 200,表示期望收到的下一个报文的序号。
-
标志位 CWR(Congestion Window Reduce):拥塞窗口减少标志;
-
标志位 ECE(ECN Echo):ECE 标志等于 1 时,通知接收方,表示接收方到这边的网络存在拥塞;
-
标志位 URG(Urgent):本报文是否包含紧急数据,只有当 URG=1 时,"校验和" 后面的 "紧急指针" 字段才有效;
-
标志位 ACK(Acknowledgement):ACK=1 则表示前面发送的确认号是否有效,TCP 连接建立之后,ACK 必须设置为 1;
-
标志位 PSH(Push):PSH 设置为 1 则表示需要将收到的数据立即传输给上层应用,否则先放缓存;
-
标志位 RST(Reset):RST 设置为 1 则表示 TCP 连接出现异常,需要强制断开;
-
标志位 SYN(Synchronize):SYN 设置为 1 则表示希望建立连接;
-
标志位 FIN(Finsish):FIN 设置为 1 则表示数据已经发送完成,可以断开 TCP 连接。
上述定义中,序号、确认号以及 ACK、SYN 和 FIN 标志位是我们需要重点关注的部分,因为在 TCP 建立连接和断开连接时会涉及到。
2.3 TCP 三次握手
面试官提问: TCP 是如何建立连接的?分析下每个步骤传输了什么样的数据?
题目解析:
首先从行为上分析,TCP 建立连接需要发送三次报文,也就是 "三次握手" 的过程。
我们定义发送报文的一方是客户端,接收报文的一方是服务器端。
首先服务器端处于监听(LISTEN)的状态,否则不会收到客户端发来的请求。
(1)第一次握手:客户端往服务器端发送一个请求建立连接报文,报文首部 SYN 标志位 = 1,给定一个初始的 Seq 序号 x。之后客户端进入 SYN_SEN(同步发送)状态;
(2)第二次握手:服务器端收到请求报文,如果同意建立连接,则向客户端发送确认报文。确认报文中 SYN 标志位 = 1,ACK 标志位 = 1,同时给定一个 Seq 序号 y,Ack 确认号 x+1,之后服务器端进入 SYN_RCVD(同步已发送)状态;
(3)第三次握手:客户端收到来自服务器端的确认报文之后,还需要向服务器端发送确认报文,报文首部 ACK 标志位 = 1,Ack 确认号为 y+1,发送之后客户端进入 ESTABLISHED(已建立连接)的状态。服务器端收到确认报文后,也会进入 ESTABLISHED 状态,在此之后,客户端和服务器端可以开始 TCP 通信了。
2.4 TCP 三次握手的必要性
2.4.1 三次握手的意义
面试官提问: TCP 建立连接为什么需要三次握手?可以只有两次握手吗?第三次握手有什么意义?
题目解析:
紧接上面一个问题,如果我们能够成功画出 TCP 三次握手的过程,以及分析每个过程传输报文的首部内容,那么面试官大概率会抛出这样一个问题,考察我们对 TCP 三次握手的理解。
首先从定性角度来看,分析三次握手每个步骤的意义:
(1)第一次握手:客户端发送报文,服务器端接收报文,如果成功接收,说明客户端的发送能力、服务器端的接收能力符合预期;
(2)第二次握手:服务器端发送报文,客户端接收报文,如果成功接收。从客户端的角度来看:客户端的发送和接收能力符合预期,服务器端的发送和接收能力符合预期,可以建立连接。但是从服务器端的角度来看:客户端的发送能力符合预期(第一次握手),服务器端的接收能力符合预期(第二次握手),但是因为收不到客户端的反馈(无法获知第二次握手的报文是否成功抵达客户端),那么只能得出服务器端的发送能力和客户端的接收能力不一定符合预期的结论;
(3)第三次握手:客户端发送报文,服务器端接收报文,如果接收成功,从服务器端的角度来看:客户端的报文接收能力以及服务器端的报文发送能力都符合预期。
经过三次握手的过程,客户端和服务器端都明确对方以及自己能成功接收和发送信息,所以就可以开始正常通信。
2.4.2 假设如果只有两次握手过程,是否能顺利建立 TCP 连接?
《计算机网络》 一书中对此进行了解释,三次握手的目的是 "为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误"。
如果 TCP 只有两次握手,如果服务器端发送的第一个请求建立连接的报文在某个网络节点长时间阻塞,等到连接释放之后才抵达服务器端。本来这是一个早就失效的报文,但是服务器端收到这个失效的请求建立连接报文之后,会误以为是客户端需要建立一个新的连接请求,于是向客户端发送 ACK 确认报文,同意建立连接,这时候因为已经完成了两次握手,所以新的连接就会建立成功,这种情况显然不符合预期。
如果是三次握手,客户端不会向服务器端发送 ACK 确认报文,所以服务器端超过最长等待时间后,会认为客户端没有要求建立请求,这个无效报文最终会失效。
3. 小结
本章节给大家介绍了 TCP 和 UDP 协议的报文格式以及区别,分析了 TCP 建立连接的握手过程,需要大家能够准确画出 TCP 握手每个过程的标志位以及序号、确认号,并且从原理上理解三次握手的必要性,下一章节会继续给大家分析 TCP 四次挥手过程。