- UDP 和 TCP 的特点与区别
用户数据报协议 UDP(User Datagram Protocol)
是无连接的,尽最大可能交付,没有拥塞控制,面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信。
传输控制协议 TCP(Transmission Control Protocol)
是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)。
- UDP 、TCP 首部格式
UDP 首部字段只有 8 个字节,包括源端口、目的端口、长度、检验和。12 字节的伪首部是为了计算检验和临时添加的。
TCP 首部格式比 UDP 复杂。
序号:用于对字节流进行编号,例如序号为 301,表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的序号应为 401。
确认号:期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701。
数据偏移:指的是数据部分距离报文段起始处的偏移量,实际上指的是首部的长度。
控制位:八位从左到右分别是 CWR,ECE,URG,ACK,PSH,RST,SYN,FIN。
CWR:CWR 标志与后面的 ECE 标志都用于 IP 首部的 ECN 字段,ECE 标志为 1 时,则通知对方已将拥塞窗口缩小;
ECE:若其值为 1 则会通知对方,从对方到这边的网络有阻塞。在收到数据包的 IP 首部中 ECN 为 1 时将 TCP 首部中的 ECE 设为 1;
URG:该位设为 1,表示包中有需要紧急处理的数据,对于需要紧急处理的数据,与后面的紧急指针有关;
ACK:该位设为 1,确认应答的字段有效,TCP规定除了最初建立连接时的 SYN 包之外该位必须设为 1;
PSH:该位设为 1,表示需要将收到的数据立刻传给上层应用协议,若设为 0,则先将数据进行缓存;
RST:该位设为 1,表示 TCP 连接出现异常必须强制断开连接;
SYN:用于建立连接,该位设为 1,表示希望建立连接,并在其序列号的字段进行序列号初值设定;
FIN:该位设为 1,表示今后不再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位置为 1 的 TCP 段。
每个主机又对对方的 FIN 包进行确认应答之后可以断开连接。不过,主机收到 FIN 设置为 1 的 TCP 段之后不必马上回复一个 FIN 包,而是可以等到缓冲区中的所有数据都因为已成功发送而被自动删除之后再发 FIN 包;
窗口:窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。
- 什么是 TCP 的三次握手?
TCP 三次握手
客户端打算建立连接时,发送一个 TCP 首部 SYNC 被置为 1 且序号 SEQ 为 n 的报文。
ACK 是累积的,一个确认字节号 N 的 ACK 表示所有直到 N 的字节(不包括 N)已经成功被接收了。这样的好处是如果一个 ACK 丢失,很可能后续的 ACK 就足以确认前面的报文段了。
一个完整的 TCP 连接是双向和对称的,数据可以在两个方向上平等地流动。给上层应用程序提供一种双工服务。一旦建立了一个连接,这个连接的一个方向上的每个 TCP 报文段都包含了相反方向上的报文段的一个 ACK。
序列号的作用是使得一个 TCP 接收端可丢弃重复的报文段,记录以杂乱次序到达的报文段。因为 TCP 使用 IP 来传输报文段,而IP 不提供重复消除或者保证次序正确的功能。
另一方面,TCP 是一个字节流协议,绝不会以杂乱的次序给上层程序发送数据。因此 TCP 接收端会被迫先保持大序列号的数据不交给应用程序,直到缺失的小序列号的报文段被填满。
- 为什么是 TCP 的四次挥手?
TCP 四次挥手
客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。 客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态 服务器收到了 ACK 应答报文后,就进入了 CLOSED 状态,至此服务端已经完成连接的关闭。 客户端在经过 2MSL 一段时间后,自动进入 CLOSED 状态,至此客户端也完成连接的关闭。
- TCP 短连接和长连接的区别
短连接:Client 向 Server 发送消息,Server 回应 Client,然后一次读写就完成了,这时候双方任何一个都可以发起 close 操作,不过一般都是 Client 先发起 close 操作。短连接一般只会在 Client/Server 间传递一次读写操作。
短连接的优点:管理起来比较简单,建立存在的连接都是有用的连接,不需要额外的控制手段。
长连接:Client 与 Server 完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。
在长连接的应用场景下,Client 端一般不会主动关闭它们之间的连接,Client 与 Server 之间的连接如果一直不关闭的话,随着客户端连接越来越多,Server 压力也越来越大,这时候 Server 端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致 Server 端服务受损;如果条件再允许可以以客户端为颗粒度,限制每个客户端的最大长连接数,从而避免某个客户端连累后端的服务。
长连接和短连接的产生在于 Client 和 Server 采取的关闭策略,具体的应用场景采用具体的策略。
- TCP粘包、拆包及解决办法
由前两节可知,UDP 是基于报文发送的,UDP首部采用了 16bit 来指示 UDP 数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。
而 TCP 是基于字节流的,虽然应用层和 TCP 传输层之间的数据交互是大小不等的数据块,但是 TCP 并没有把这些数据块区分边界,仅仅是一连串没有结构的字节流;另外从 TCP 的帧结构也可以看出,在 TCP 的首部没有表示数据长度的字段,基于上面两点,在使用 TCP 传输数据时,才有粘包或者拆包现象发生的可能。
粘包、拆包解决办法
由于 TCP 本身是面向字节流的,无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决,根据业界的主流协议的解决方案,归纳如下:
消息定长:发送端将每个数据包封装为固定长度(不够的可以通过补 0 填充),这样接收端每次接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。 设置消息边界:服务端从网络流中按消息边界分离出消息内容。在包尾增加回车换行符进行分割,例如 FTP 协议。 将消息分为消息头和消息体:消息头中包含表示消息总长度(或者消息体长度)的字段。 更复杂的应用层协议比如 Netty 中实现的一些协议都对粘包、拆包做了很好的处理。
- TIME-WAIT 状态为什么需要等待 2MSL
2MSL,2 Maximum Segment Lifetime,即两个最大段生命周期
1个 MSL 保证四次挥手中主动关闭方最后的 ACK 报文能最终到达对端 1个 MSL 保证对端没有收到 ACK 那么进行重传的 FIN 报文能够到达
- TCP 是如何保证可靠性的
TCP使用多种机制来保证可靠性:
1.确认和重传:发送方将每个数据包标记为已发送,并在一定时间内等待接收方的确认。如果发送方没有收到确认,它会假设数据包丢失,并重新发送它。
2.序列号和排序:每个数据包都有一个唯一的序列号,接收方使用这些序列号来确保接收到的数据包按正确的顺序重组。
3.滑动窗口:发送方和接收方都维护一个滑动窗口,它表示可以发送或接收的数据的范围。发送方仅发送窗口内的数据,并等待接收方的确认。接收方仅接收窗口内的数据,并将窗口外的数据丢弃。
4.流量控制:接收方可以使用滑动窗口通知发送方它的接收能力。如果接收方的缓冲区已满,它可以减小窗口大小,告诉发送方减慢发送速度,以避免数据丢失。
5 拥塞控制:TCP使用拥塞窗口来限制发送方的发送速度,以避免网络拥塞。如果网络拥塞,发送方会拥塞控制算法来减小发送速度,从而避免进一步加剧拥塞。
通过这些机制的组合,TCP能够在不可靠的网络中提供可靠的数据传输服务。
- TCP 重传机制
TCP 重传机制是为了保证数据的可靠传输而设计的。当发送方发送一个 TCP 报文段后,会启动一个定时器,如果在定时器时间内没有收到接收确认(ACK)报文段,发送方会认为数据丢失,会进行重传。
最佳回答应该包括以下几个要点:
- TCP 重传是通过超时重传和快速重传两种方式实现的。
- 超时重传:发送方设置一个定时器,在超过定时器时间后仍未收到 ACK 时,认为数据丢失,触发重传操作。
- 快速重传:当发送方连续接收到3个重复的 ACK 时,表明接收方已经收到后续报文段,但是发生了丢包。此时发送方可以不等待超时,立即重传丢失的报文段。
- TCP 还采用了滑动窗口机制来优化重传,在收到重复的 ACK 时,通过调整滑动窗口来进行快速重传或退避重传。
- TCP 还会对重传的报文段设置一个指数级的退避时间,以防止过多重传导致网络拥塞。
另外,面试者可以进一步讨论 TCP 重传机制的一些细节,如选择性重传、慢启动等。
- TCP的流量控制
TCP的流量控制是一种机制,用于控制发送方向接收方发送的数据量,以防止接收方无法及时处理大量数据而导致数据丢失或拥塞的问题。最佳回答应该包含以下几个要点:
- TCP的流量控制通过滑动窗口机制实现,接收方使用窗口大小告知发送方自己能够接收的数据量。
- 发送方根据接收方的窗口大小来确定发送的数据量,确保发送的数据不超过接收方所能接收的数据量。
- 当发送方发送的数据量超过接收方窗口的大小时,接收方将不对这些数据进行确认,从而告知发送方减缓发送的速率。
- 使用流量控制可以防止接收方由于无法及时处理大量数据而导致的数据丢失,同时也能避免网络拥塞。
- 流量控制是TCP的一个重要特性,它可以根据接收方的能力来动态调整发送速率,以适应不同的网络环境和接收方的处理能力。
- TCP的拥塞控制
TCP的拥塞控制是一种机制,用于在网络中控制数据包的发送速率,以防止网络拥塞和丢包。它通过一系列的算法来监测网络条件,并根据这些条件动态调整发送速率。
拥塞控制的主要目标是保持网络的可靠性和公平性。为了实现这些目标,TCP拥塞控制采用了一些重要的算法,包括慢启动、拥塞避免、快速重传和快速恢复。
-
慢启动:在开始发送数据时,TCP发送方会以指数级增加发送速率,直到网络开始出现拥塞。这个过程可以确保在网络负载较轻时,TCP流可以快速占用可用带宽。
-
拥塞避免:一旦网络开始出现拥塞,TCP会进入拥塞避免阶段。在这个阶段,TCP会以线性增加发送速率,以更加谨慎地使用网络资源,避免进一步加剧拥塞。
-
快速重传和快速恢复:当接收方检测到数据包丢失时,它会发送一个重复确认给发送方。一旦连续收到3个重复确认,发送方会立即重传丢失的数据包,并将发送速率减半。这个机制可以快速恢复数据包丢失引起的拥塞,并避免慢启动的过程。
总结来说,最佳的回答应该包括对TCP拥塞控制的基本原理和核心算法的了解,以及对其作用和目标的详细解释。面试者还可以提及其他相关的拥塞控制算法,如Reno和Cubic,并对其与TCP的区别进行讨论。另外,了解TCP拥塞控制在实际场景中的应用和挑战也会给出更好的回答。