TCP面试题整理(附答案,持续更新)

817 阅读21分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

计算机网络的面试题已在程序员面试中屡见不鲜,这里面的概念纷繁复杂,而且平时工作中很少用到,看了后很容易忘。

于是,我针对计算机网络面试题做了一系列的整理,我参考了大量网络上的资源以及经典参考书,争取能把具体的面试题目给讲明白讲透彻,强调理解记忆,拒绝八股文!!。这一篇内容,既是自我的学习总结,也希望能帮助到正在复习面试的朋友。

本系列文章一共分为两篇,TCP篇HTTP篇

TCP篇

TCP/IP与OSI分层之间的关系

image.png

OSI七层模型

  • 物理层:比特流。网卡
  • 数据链路层:如何格式化数据,确保数据传输可靠性,比特流组成帧。交换机
  • 网络层:网络地址翻译成物理地址,数据包,IP协议。路由器
  • 传输层:流量控制,TCP/UDP,分段
  • 会话层:建立和管理应用程序员之间的通信
  • 表示层:数据
  • 应用层:HTTP

OSI并不是一个标准,而是一个概念。

OSI 七层模型在提出时的出发点是基于标准化的考虑,而没有考虑到具体的市场需求,使得该模型结构复杂,部分功能冗余,因而完全实现 OSI 参考模型的系统不多。而 TCP/IP 参考模型直接面向市场需求,实现起来也比较容易,因此在一经提出便得到了广泛的应用。

OSI参考模型注重“通信协议必要的功能是什么”,而TCP/IP则更强调“在计算机上实现协议应该开发哪种程序”。

什么是TCP/IP协议

通常使用的网络(包括互联网)是在 TCP/IP 协议族的基础上运作的。而 HTTP 属于它内部的一个子集。

计算机与网络设备要相互通信,双方就必须基于相同的方法。比如,如何探测到通信目标、由哪一边先发起通信、使用哪种语言进行通信、怎样结束通信等规则都需要事先确定。不同的硬件、操作系统之间的通信,所有的这一切都需要一种规则。而我们就把这种规则称为协议(protocol)。

协议中存在各式各样的内容。从电缆的规格到 IP 地址的选定方法、寻找异地用户的方法、双方建立通信的顺序,以及 Web 页面显示需要处理的步骤,等等。

像这样把与互联网相关联的协议集合起来总称为 TCP/IP。

图:TCP/IP 是互联网相关的各类协议族的总称。

image.png

TCP/IP四层模型

TCP/IP 协议族按层次分别分为以下 4 层:应用层、传输层、网络层和数据链路层。

应用层

应用层决定了向用户提供应用服务时通信的活动。TCP/IP 协议族内预存了各类通用的应用服务。比如,FTP(File Transfer Protocol,文件传输协议)和 DNS(Domain Name System,域名系统)服务就是其中两类。HTTP 协议也处于该层。

传输层

传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。

在传输层有两个性质不同的协议:TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Data Protocol,用户数据报协议)。

网络层

网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。该层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据包传送给对方。

与对方计算机之间通过多台计算机或网络设备进行传输时,网络层所起的作用就是在众多的选项内选择一条传输路线。

链路层

用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC(Network Interface Card,网络适配器,即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。硬件上的范畴均在链路层的作用范围之内。

image.png

发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该所属的首部信息。反之,接收端在层与层传输数据时,每经过一层时会把对应的首部消去。

IP协议

IP(Internet Protocol)网际协议位于网络层。

IP 协议的作用是把各种数据包传送给对方。而要保证确实传送到对方那里,则需要满足各类条件。其中两个重要的条件是 IP 地址和 MAC地址(Media Access Control Address)。

IP 地址指明了节点被分配到的地址,MAC 地址是指网卡所属的固定地址。IP 地址可以和 MAC 地址进行配对。IP 地址可变换,但 MAC地址基本上不会更改。

TCP协议

TCP 位于传输层,提供可靠的字节流服务。

所谓的字节流服务(Byte Stream Service)是指,为了方便传输,将大块数据分割成以报文段(segment)为单位的数据包进行管理。而可靠的传输服务是指,能够把数据准确可靠地传给对方。一言以蔽之,TCP 协议为了更容易传送大数据才把数据分割,而且 TCP 协议能够确认数据最终是否送达到对方。

TCP简介:

  • 面向连接的,可靠的,基于字节流的传输层通信协议
  • 将应用层的数据流分隔成报文段并发送给目标节点的TCP层
  • 数据包都有序号,对方收到则发送ACK确认,未收到则重传
  • 使用校验和来检验数据在传输过程中是否有误

TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。

  • 面向连接:一定是一对一才能连接,不能像UDP协议可以一个主机同时向多个主机发送消息,也就是一对多无法做到。
  • 可靠的:无论网络链路中出现了怎样的链路变化,TCP都可以保证一个报文一定能到达接收端。
  • 字节流:消息是没有边界的,所以无论我们消息有多大都可以进行传输。并且消息是有序的,当前一个消息没有收到的时候,即使它先收到了后面的字节,那么也不能扔给应用层去处理,同时对重复的报文会自动丢弃。

如何理解TCP的面向连接

所谓的建立连接,是为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态,用这样的数据结构来保证所谓的面向连接的特性。

TCP 提供可靠交付。通过 TCP 连接传输的数据,无差错、不丢失、不重复、并且按序到达。

IP 包是没有任何可靠性保证的。UDP 继承了 IP 包的特性,不保证不丢失,不保证按顺序到达。

如何理解TCP的面向字节流

TCP 是面向字节流的。发送的时候发的是一个流,没头没尾。IP 包可不是一个流,而是一个个的 IP 包。之所以变成了流,这也是 TCP 自己的状态维护做的事情。而 UDP 继承了 IP 的特性,基于数据报的,一个一个地发,一个一个地收。

还有 TCP 是可以有拥塞控制的。它意识到包丢弃了或者网络的环境不好了,就会根据情况调整自己的行为,看看是不是发快了,要不要发慢点。UDP 就不会,应用让我发,我就发,管它洪水滔天。

各种协议与HTTP协议的关系

image.png

什么是三次握手(重点)

为了准确无误地将数据送达目标处,TCP 协议采用了三次握手(three-way handshaking)策略。用 TCP 协议把数据包送出去后,TCP不会对传送后的情况置之不理,它一定会向对方确认是否成功送达。

握手过程中使用了 TCP 的标志(flag) —— SYN(synchronize)和 ACK(acknowledgement)。

发送端首先发送一个带 SYN 标志的数据包给对方。接收端收到后,回传一个带有 SYN/ACK 标志的数据包以示传达确认信息。最后,发送端再回传一个带 ACK 标志的数据包,代表“握手”结束。

若在握手过程中某个阶段莫名中断,TCP 协议会再次以相同的顺序发送相同的数据包。

除了上述三次握手,TCP 协议还有其他各种手段来保证通信的可靠性。

image.png

三次握手流程如下:

  • 客户端–发送带有 SYN 标志的数据包–一次握手–服务端
  • 服务端–发送带有 SYN/ACK 标志的数据包–二次握手–客户端
  • 客户端–发送带有带有 ACK 标志的数据包–三次握手–服务端

为什么要三次握手,两次不行吗(重点)

三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。

第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常

第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常

第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常

所以三次握手就能确认双发收发功能都正常,缺一不可。

建立连接后,Client出现故障怎么办

保活机制

  • 向对方发送保活探测报文,如果未收到响应则继续发送
  • 尝试次数达到保活探测数仍未收到响应则中断连接

为什么要四次挥手(重点)

image.png

断开一个 TCP 连接则需要“四次挥手”:

  • 客户端-发送一个 FIN,用来关闭客户端到服务器的数据传送
  • 服务器-收到这个 FIN,它发回一 个 ACK,确认序号为收到的序号加1 。和 SYN 一样,一个 FIN 将占用一个序号
  • 服务器-关闭与客户端的连接,发送一个FIN给客户端
  • 客户端-发回 ACK 报文确认,并将确认序号设置为收到序号加1

任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。

推荐一篇文章:blog.csdn.net/qzcsu/artic…

为什么会有TIME_WAIT状态?

  • 确保有足够的时间让对方收到ACK包
  • 避免新旧连接混淆

服务器出现大量CLOSE_WAIT状态的原因

  • 对方关闭socket连接,我方忙于读或写,没有及时关闭连接
    • 检查代码,特别是释放资源的代码
    • 检查配置,特别是处理请求的线程配置(可用netstat排查)
netstat -n | awk '/^tcp/{++S[$NF]}END{for (a in S)} print a,S[a]'

UDP协议

包头:源端口,目标端口,长度,校验值

特点

  • 面向非连接
  • 不维护连接状态,支持同时向多个客户端传输相同的消息
  • 数据包报头只有8个字节,额外开销较小
  • 吞吐量只受限于数据生成速率、传输速率以及机器性能
  • 尽最大努力交付,不保证可靠交付,不需要维持复杂的链接状态表
  • 面向报文,不对应用程序提交的报文信息进行拆分或者合并

TCP和UDP的区别(重点)

类型是否面向连接传输可靠性传输形式传输效率所需资源应用场景首部字节
TCP面向连接可靠字节流要求通信数据可靠20-60
UDP无连接不可靠数据报文段要求通信速度高8个字节

TCP:面向连接、可靠的、基于字节流

UDP:无连接、不可靠、面向报文

UDP 在传送数据之前不需要先建立连接,远地主机在收到 UDP 报文后,不需要给出任何确认。虽然 UDP 不提供可靠交付,但在某些情况下 UDP 确是一种最有效的工作方式(一般用于即时通信),比如: QQ 语音、 QQ 视频 、直播等等

TCP 提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。 TCP 不提供广播或多播服务。由于 TCP 要提供可靠的,面向连接的传输服务(TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源),这一难以避免增加了许多开销,如确认,流量控制,计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多处理机资源。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。

具体各个指标的对比:

连接

  • TCP是面向连接的传输层协议,传输数据前先要建立连接
  • UDP是不需要连接,即刻传输数据

服务对象

  • TCP是一对一的两点服务,即一条连接只有两个端点
  • UDP支持一对一、一对多、多对多的交互通信

可靠性

  • TCP是可靠交付数据的,数据可以无差错、不丢失、不重复、按需到达。
  • UDP是尽最大努力交付,不保证可靠交付数据。

拥塞控制、流量控制

  • TCP有拥塞控制和流量控制机制,保证数据传输的安全性
  • UDP则没有,即使网络非常拥堵了,也不会影响UDP的发送速率

首部开销

  • TCP首部长度较长,会有一定的开销,首部在没有使用选项字段时是20个字节,如果使用了选项字段则会变长的。
  • UDP首部只有8个字节,并且是固定不变的,开销较小。

传输方式

  • TCP是流式传输,没有边界,但保证顺序和可靠
  • UDP是一个包一个包的发送,是有边界的,但可能会丢包和乱序

由于TCP是面向连接,能保证数据的可靠性交付,因此经常用于:

  • FTP 文件传输
  • HTTP / HTTPS

由于 UDP 面向无连接,它可以随时发送数据,再加上UDP本身的处理既简单又高效,因此经常用于:

  • 包总量较少的通信,如 DNS 、SNMP 等
  • 视频、音频等多媒体通信
  • 广播通信

TCP协议如何保证可靠传输(重要)

  1. 应用数据被分割成 TCP 认为最适合发送的数据块。
  2. TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
  3. 校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
  4. TCP 的接收端会丢弃重复的数据。
  5. 流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)
  6. 拥塞控制: 当网络拥塞时,减少数据的发送。
  7. ARQ协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
  8. 超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

重传机制

TCP 实现可靠传输的方式之一,是通过序列号与确认应答。

在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个确认应答消息,表示已收到消息。

但在错综复杂的网络,并不一定能如上图那么顺利能正常的数据传输,万一数据在传输过程中丢失了呢?

所以 TCP 针对数据包丢失的情况,会用重传机制解决。

自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧,它通常会重新发送。ARQ包括停止等待ARQ协议和连续ARQ协议。

滑动窗口

我们都知道 TCP 是每发送一个数据,都要进行一次确认应答。当上一个数据包收到了应答了, 再发送下一个。

这个模式就有点像我和你面对面聊天,你一句我一句。但这种方式的缺点是效率比较低的。

如果你说完一句话,我在处理其他事情,没有及时回复你,那你不是要干等着我做完其他事情后,我回复你,你才能说下一句话,很显然这不现实。

所以,这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低。

为解决这个问题,TCP 引入了窗口这个概念。即使在往返时间较长的情况下,它也不会降低网络通信的效率。

那么有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值。

TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。

RTT和RTO:

  • RTT:发送一个数据包到收到对应的ACK,所花费的时间
  • RTO:重传时间间隔

TCP使用滑动窗口做流量控制与乱序重排

  • 保证TCP的可靠性
  • 保证TCP的流控特性

流量控制

发送方不能无脑的发数据给接收方,要考虑接收方处理能力。

如果一直无脑的发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费。

为了解决这种现象发生,TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。

拥塞控制

前面的流量控制是避免「发送方」的数据填满「接收方」的缓存,但是并不知道网络的中发生了什么。

一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。

在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大….

所以,TCP 不能忽略网络上发生的事,它被设计成一个无私的协议,当网络发送拥塞时,TCP 会自我牺牲,降低发送的数据量。

于是,就有了拥塞控制,控制的目的就是避免「发送方」的数据填满整个网络。

为了在「发送方」调节所要发送数据的量,定义了一个叫做「拥塞窗口」的概念。

在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。

TCP的拥塞控制采用了四种算法,即 慢开始 、 拥塞避免 、快重传 和 快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理 AQM),以减少网络拥塞的发生。

前面的滑动窗口 rwnd 是怕发送方把接收方缓存塞满,而拥塞窗口 cwnd,是怕把网络塞满。

这里有一个公式 LastByteSent - LastByteAcked <= min {cwnd, rwnd} ,是拥塞窗口和滑动窗口共同控制发送的速度。

顺序问题、丢包问题、流量控制都是通过滑动窗口来解决的,这其实就相当于你领导和你的工作备忘录,布置过的工作要有编号,干完了有反馈,活不能派太多,也不能太少;

拥塞控制是通过拥塞窗口来解决的,相当于往管道里面倒水,快了容易溢出,慢了浪费带宽,要摸着石头过河,找到最优值。

UDP有拥塞控制吗

TCP的粘包是什么

tcp底层的粘包/拆包机制

业务上一个包可能被tcp拆成多个包发送

分析TCP粘包、拆包问题的产生原因:

  • 应用程序write写入的字节大小大于套接口发送缓冲区的大小
  • 进行MSS大小的TCP分段、以太网帧的payload大于MTU进行IP分片等

Netty TCP拆包粘包问题的处理

粘包拆包问题的解决方案,根据业界主流协议,有三种方案:

  • 消息定长,例如每个报文的大小固定为200个字节,如果不够,空位补空格
  • 在包尾部增加特殊字符进行分割,例如加回车等
  • 消息分为消息头和消息体,在消息头中包含表示消息总长度的字段,然后进行业务处理

TCP和UDP能监听同一个端口吗

可以。

IP数据包首部有个叫做协议的字段,指出了上层协议是TCP还是UDP还是其他。操作系统有能力根据接受的报文的IP字段里面的协议部分判断这个报文是什么报文,就是说,系统读数据的时候还没有读到上层报文(TCP/UDP)的时候已经知道上层是什么报文了,直接交给相关的内核进程或协议栈处理就可以了。而在同一个协议内部端口号唯一。

有了tcp的长连接,为什么还要心跳检测

todo

参考资料