一文弄懂TCP常见面试题

1.OSI参考模型分为多少层?每一层具体负责和对应哪些功能?每一层的代表协议有哪些?

1、物理层:是参考模型的最低层。该层是网络通信的数据传输介质,由连接不同结点的电缆与设备共同构成。主要跟功能是:利用传输介质为数据链路层提供物理连接,负责处理数据传输并监控数据出错率,以便数据流的透明传输。

2、数据链路层:四参考模型的第二层。主要功能是:在物理层提供的服务基础上,在通信的实体间建立数据链路连接,传输以“帧”为单位的数据包,并采用差错控制与流量控制方法,使有差错的物理线路变成无差错的数据链路。

3、网络层:是参考模型的第三层。主要功能是:为数据在节点之间传输创建逻辑链路,通过路由选择算法为分组通过通信子网选择最适当的路径,以及实现拥塞控制、网络互连等功能。

4、传输层:是参考模型的第四层。主要功能是:向用户提供可靠地端到端服务,处理数据包错误、数据包次序,以及其他一些关键传输问题。传输层向高层屏蔽了下层数据通信的细节。因此,它是计算机通信体系结构中关键的一层。

5、会话层:是参考模型的第五层。主要功能是:负责维扩两个结点之间的传输连接,以便确保点到点传输不中断,以及管理数据交换等功能。

6、表示层:是参考模型的第六层。主要功能是:用于处理在两个通信系统中交换信息的表示方法,主要包括数据格式变换、数据加密与解密、数据压缩与恢复等功能。

7、应用层:是参考模型的最高层。主要功能是:为应用软件提供了很多服务,比如文件服务器、数据库服务、电子邮件与其他网络软件服

 

2.tcp头部格式是怎样的?都有哪些字段?

序列号:在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就 「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。

确认应答号:指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数 据都已经被正常接收。用来解决不丢包的问题。

控制位:

ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必 须设置为 1 。

RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
SYN:该位为 1 时,表示希望建立连接,并在其「序列号」的字段进行序列号初始值的设定。

FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的 主机之间就可以相互交换 FIN 位为 1 的 TCP 段。 

3.为什么需要tcp协议?

IP 层是「不可靠」的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性。

因为 TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。

4.如何唯一确定一个tcp连接呢?

TCP 四元组可以唯一的确定一个连接,四元组包括如下: 源地址 源端口 目的地址 目的端口 

源地址和目的地址的字段(32位)是在 IP 头部中,作用是通过 IP 协议发送报文给对方主机。 

源端口和目的端口的字段(16位)是在 TCP 头部中,作用是告诉 TCP 协议应该把报文发给哪个进程 。

5.有一个 IP 的服务器监听了一个端口,它的 TCP 的最大连接数是多少? 

服务器通常固定在某个本地端口上监听,等待客户端的连接请求。 因此,客户端 IP 和 端口是可变的,其理论值计算公式如下: 最大TCP连接数=客户端的IP数X客户端的端口数

对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最 大 TCP 连接数,约为 2 的 48 次方。 

当然,服务端最大并发 TCP 连接数远不能达到理论上限。 首先主要是文件描述符,socket都是文件,所以要首先通过ulimit配置文件描述符的数目;

另一个是内存限制,每个 TCP 连接都要占用一定内存,操作系统的内存是有限的 。

6.MSS 和 MTU是什么?

最大报文段长度(MSS)与最大传输单元(Maximum Transmission Unit, MTU)均是协议用来定义最大长度的。不同的是,MTU应用于OSI模型的第二层数据链接层,并无具体针对的协议。

MTU限制了数据链接层上可以传输的数据包的大小,也因此限制了上层(网络层)的数据包大小。例如,如果已知某局域网的MTU为1500字节,则在网络层的因特网协议(Internet Protocol, IP)里,

最大的数据包大小为1500字节(包含IP协议头)。MSS针对的是OSI模型里第四层传输层的TCP协议。因为MSS应用的协议在数据链接层的上层,MSS会受到MTU的限制。

7.UDP 和 TCP 有什么区别呢?分别的应用场景是? 

 UDP 不提供复杂的控制机制,利用 IP 提供面向「无连接」的通信服务。UDP 协议真的非常简,头部只有 8 个字节( 64 位),UDP 的头部格式如下: 

目标和源端口:主要是告诉 UDP 协议应该把报文发给哪个进程。 包⻓度:该字段保存了 UDP 首部的⻓度跟数据的⻓度之和。 校验和:校验和是为了提供可靠的 UDP 首部和数据而设计。 

TCP 和 UDP 区别:

1. 连接

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

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

3. 可靠性

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

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

5. 首部开销

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

6. 传输方式

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

7. 分片不同
TCP 的数据大小如果大于 MSS 大小,则会在传输层进行分片,目标主机收到后,也同样在传输层组装 TCP数据包,如果中途丢失了一个分片,只需要传输丢失的这个分片

UDP 的数据大小如果大于 MTU 大小,则会在 IP 层进行分片,目标主机收到后,在 IP 层组装完数据,接着 再传给传输层,但是如果中途丢了一个分片,在实现可靠传输的 UDP 时则就需要

传所有的数据包,这样 传输效率非常差,所以通常 UDP 的报文应该小于 MTU。 

TCP 和 UDP 应用场景:

由于 TCP 是面向连接,能保证数据的可靠性交付,因此经常用于:FTP 文件传输 、HTTP / HTTPS 

由于 UDP 面向无连接,它可以随时发送数据,再加上UDP本身的处理既简单又高效,因此经常用于:包总量较少的通信,如 DNS 、SNMP 等; 视频、音频等多媒体通信;广播通信 

8.简述TCP 三次握手过程和状态变迁 

一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态 

客户端会随机初始化序号( client_isn ),将此序号置于 TCP 首部的「序号」字段中,同时把 SYN 标志 位置为 1 ,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,

该报文不 包含应用层数据,之后客户端处于 SYN-SENT 状态 

服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号( server_isn ),将此序号填入TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1 ,

接着把 SYN和 ACK 标志位置为 1 。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN- RCVD 状态。 

客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位 置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,

这次报文可以携带客 户到服务器的数据,之后客户端处于 ESTABLISHED 状态。服务器收到客户端的应答报文后,也进入 ESTABLISHED 状态。 

从上面的过程可以发现第三次握手是可以携带数据的,前两次握手是不可以携带数据的,这也是面试常问的题。 

 9.为什么客户端和服务端的初始序列号 ISN 是不相同的? 

如果一个已经失效的连接被重用了,但是该旧连接的历史报文还残留在网络中,如果序列号相同,那么就无法分辨出该报文是不是历史报文,如果历史报文被新的连接接受了,则会产生数据错乱。所以,每次建立连接前 新初始化一个序列号主要是为了通信双方能够根据序号将不属于本连接的报文段丢弃。 另一方面是为了安全性,防止黑客伪造的相同序列号的 TCP 报文被对方接收。 

10.既然 IP 层会分片,为什么 TCP 层还需要 MSS 呢? 

MTU :一个网络包的最大⻓度,以太网中一般为 1500 字节;
MSS :除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大⻓度;

如果在 TCP 的整个报文(头部 + 数据)交给 IP 层进行分片,会有什么异常呢?

当 IP 层有一个超过 MTU 大小的数据(TCP 头部 + TCP 数据)要发送,那么 IP 层就要进行分片,把数据分片成 若干片,保证每一个分片都小于 MTU。把一份 IP 数据报进行分片以后,由目标主机的 IP 层来进行 新组装后, 再交给上一层 TCP 传输层。

这看起来井然有序,但这存在隐患的,那么当如果一个 IP 分片丢失,整个 IP 报文的所有分片都得重传。 因为 IP 层本身没有超时 传机制,它由传输层的 TCP 来负责超时和 传。

当接收方发现 TCP 报文(头部 + 数据)的某一片丢失后,则不会响应 ACK 给对方,那么发送方的 TCP 在超时 后,就会 发「整个 TCP 报文(头部 + 数据)」。

因此,可以得知由 IP 层进行分片传输,是非常没有效率的。

所以,为了达到最佳的传输效能 TCP 协议在建立连接的时候通常要协商双方的 MSS 值,当 TCP 层发现数据超过 MSS 时,则就先会进行分片,当然由它形成的 IP 包的⻓度也就不会大于 MTU ,自然也就不用 IP 分片了。 

11.什么是 SYN 攻击?如何避免 SYN 攻击? 

SYN 攻击

我们都知道 TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到 一个 SYN 报文,就进入 SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的ACK 应答,久而久之就会占满服务端的 SYN 接收队列(未连接队列),使得服务器不能为正常用户服务。 

避免 SYN 攻击方式一

其中一种解决方式是通过修改 Linux 内核参数,控制队列大小和当队列满时应做什么处理。当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。控制该队列的最大值如下,参数:net.core.netdev_max_backlog

SYN_RCVD 状态连接的最大个数: net.ipv4.tcp_max_syn_backlog 

超出处理能时,对新的 SYN 直接回报 RST,丢弃连接: net.ipv4.tcp_abort_on_overflow 

避免 SYN 攻击方式二
我们先来看下 Linux 内核的 SYN (未完成连接建立)队列与 Accpet (已完成连接建立)队列是如何工作的? 

正常流程:

当服务端接收到客户端的 SYN 报文时,会将其加入到内核的「 SYN 队列」; 接着发送 SYN + ACK 给客户端,等待客户端回应 ACK 报文;
服务端接收到 ACK 报文后,从「 SYN 队列」移除放入到「 Accept 队列」; 应用通过调用 accpet() socket 接口,从「 Accept 队列」取出连接。 

应用程序过慢:

如果应用程序过慢时,就会导致「 Accept 队列」被占满。 

受到 SYN 攻击:
如果不断受到 SYN 攻击,就会导致「 SYN 队列」被占满。 

当 「 SYN 队列」满之后,后续服务器收到 SYN 包,不进入「 SYN 队列」; 计算出一个 cookie 值,再以 SYN + ACK 中的「序列号」返回客户端,

服务端接收到客户端的应答报文时,服务器会检查这个 ACK 包的合法性。如果合法,直接放入到「 Accept 队列」。

最后应用通过调用 accpet() socket 接口,从「 Accept 队列」取出的连接 。

12.简述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 状态,至此客户端也完成连接的关闭。 

这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。 

13.为什么挥手需要四次? 

再来回顾下四次挥手双方发 FIN 包的过程,就能理解为什么需要四次了。 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。

服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等 服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。

从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发 送,从而比三次握手导致多了一次。 

14.为什么 TIME_WAIT 等待的时间是 2MSL? 

MSL 是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最⻓时间,超过这个时 间报文将被丢弃。因为 TCP 报文基于是 IP 协议的,而 IP 头中有一个 TTL 字段,

是 IP 数据报可以经过的最大路 由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机。

MSL 与 TTL 的区别: MSL 的单位是时间,而 TTL 是经过路由跳数。所以 MSL 应该要大于等于 TTL 消耗为 0 的 时间,以确保报文已被自然消亡。

TIME_WAIT 等待 2 倍的 MSL,比较合理的解释是: 网络中可能存在来自发送方的数据包,当这些发送方的数据包 被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。

比如如果被动关闭方没有收到断开连接的最后的 ACK 报文,就会触发超时 发 Fin 报文,另一方接收到 FIN 后, 会 发 ACK 给被动关闭方, 一来一去正好 2 个 MSL。

2MSL 的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端 发的 FIN 报文,那么 2MSL 时间将重新计时。

在 Linux 系统里 2MSL 默认是 60 秒,那么一个 MSL 也就是 30 秒。Linux 系统停留在 TIME_WAIT 的时 间为固定的 60 秒。 

其定义在 Linux 内核代码里的名称为 TCP_TIMEWAIT_LEN:
#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT state, about 60 seconds */

如果要修改 TIME_WAIT 的时间⻓度,只能修改 Linux 内核代码里 TCP_TIMEWAIT_LEN 的值,并 新编译 Linux 内核。 

15.为什么需要 TIME_WAIT 状态? 

主动发起关闭连接的一方,才会有 TIME-WAIT 状态。 需要 TIME-WAIT 状态,主要是两个原因:防止具有相同「四元组」的「旧」数据包被收到;

保证「被动关闭连接」的一方能被正确的关闭,即保证最后的 ACK 能让被动关闭方接收,从而帮助其正常关 闭; 

原因一:防止旧连接的数据包

假设 TIME-WAIT 没有等待时间或时间过短,被延迟的数据包抵达后会发生什么呢? 

如上图⻩色框框服务端在关闭连接之前发送的 SEQ = 301 报文,被网络延迟了。
这时有相同端口的 TCP 连接被复用后,被延迟的 SEQ = 301 抵达了客户端,那么客户端是有可能正常接收,这个过期的报文,这就会产生数据错乱等严 的问题。

所以,TCP 就设计出了这么一个机制,经过 2MSL 这个时间,足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。

原因二,保证连接正确关闭

也就是说,TIME-WAIT 作用是等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。 假设 TIME-WAIT 没有等待时间或时间过短,断开连接会造成什么问题呢? 

如果客户端 TIME-WAIT 过短或没有,则就直接进入了 CLOSED 状态了,那么服务端则会一直处在 LASE_ACK 状态。 当客户端发起建立连接的 SYN 请求报文后,服务端会发送 RST 报文给客户端,

连接建立的过程就会被终止。

 

我们再回过头来看看,为什么 TIME_WAIT 状态要保持 60 秒呢?这与孤儿连接 FIN_WAIT2 状态默认保留 60 秒的 原理是一样的,因为这两个状态都需要保持 2MSL 时⻓。
MSL 全称是 Maximum Segment Lifetime,它定义了 一个报文在网络中的最⻓生存时间(报文每经过一次路由器的转发,IP 头部的 TTL 字段就会减 1,减到 0 时报文 就被丢弃,
这就限制了报文的最⻓存活时间)。
为什么是 2 MSL 的时⻓呢?这其实是相当于至少允许报文丢失一次。比如,若 ACK 在一个 MSL 内丢失,这样被 动方 发的 FIN 会在第 2 个 MSL 内到达,TIME_WAIT 状态的连接可以应对。

为什么不是 4 或者 8 MSL 的时⻓呢?你可以想象一个丢包率达到百分之一的糟糕网络,连续两次丢包的概率只有 万分之一,这个概率实在是太小了,忽略它比解决它更具性价比。

因此,TIME_WAIT 和 FIN_WAIT2 状态的最大时⻓都是 2 MSL,由于在 Linux 系统中,MSL 的值固定为 30 秒, 所以它们都是 60 秒。

虽然 TIME_WAIT 状态有存在的必要,但它毕竟会消耗系统资源。如果发起连接一方的 TIME_WAIT 状态过多,占 满了所有端口资源,则会导致无法创建新连接。

客户端受端口资源限制:如果客户端 TIME_WAIT 过多,就会导致端口资源被占用,因为端口就65536个,被 占满就会导致无法创建新的连接;

服务端受系统资源限制:由于一个四元组表示TCP连接,理论上服务端可以建立很多连接,服务端确实只监 听一个端口,但是会把连接扔给处理线程,所以理论上监听的端口可以继续监听。

但是线程池处理不了那么 多一直不断的连接了。所以当服务端出现大 量TIME_WAIT 时,系统资源被占满时,会导致处理不过来新的连 接;

16.tcp头部选项字段都有哪些?

 

 该篇文章大部分来自小林conding 图解网络,记录下来方便复习查看。

原文地址:https://www.cnblogs.com/kumufengchun/p/14732171.html