TCP协议——问题汇总2.0

目录

1、TCP 连接,一端断电和进程崩溃有什么区别?

2、拔掉网线后, 原本的 TCP 连接还存在吗?

 3、如何解释TCP是面向字节流的协议,UDP是面向报文的协议?

4、为什么 TCP 每次建立连接时,初始化序列号都要不一样呢?

5、已经建立的 TCP 连接,客户端中途宕机,恢复后,向服务端建立连接,此时服务端会怎么处理?

6.如何关闭一个TCP连接?

7、在FIN_WAIT_2 状态时,收到对方发来的数据,但是由于网络延迟,导致对方的FIN先到达,此时接收方是否会在接收FIN报文后直接进入TIME_WAIT 状态?

8、服务器端在 TIME_WAIT 状态的 TCP 连接,收到 SYN 后会发生什么?

9、TCP 的数据报文具体重传几次呢?

10、当网线拔掉后,再重新连接,客户端的IP地址和端口会重新随机生成嘛?

11、有哪些用于防御SYN攻击的方法?

12、延迟确认和Nagle算法混合使用会产生说明问题?

13、为什么抓包抓到的TCP挥手是三次,而不是四次?

14、为什么TCP握手是三次不是二次或四次

15、如何解决糊涂窗口综合征?

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

17、如何计算超时重传时间?

18、为什么 UDP 头部没有「首部长度」字段,而 TCP 头部有「首部长度」字段呢?

19、为什么 UDP 头部有「包长度」字段,而 TCP 头部则没有「包长度」字段呢?


1、TCP 连接,一端断电和进程崩溃有什么区别?

2拔掉网线后, 原本的 TCP 连接还存在吗?

 3、如何解释TCP是面向字节流的协议,UDP是面向报文的协议?

 

注意:在发送端,当我们调用 send 函数完成数据“发送”以后,数据并没有被真正从网络上发送出去,只是从应用程序拷贝到了操作系统内核协议栈中。至于什么时候真正被发送,取决于发送窗口、拥塞窗口以及当前发送缓冲区的大小等条件也就是说,我们不能认为每次 send 调用发送的数据,都会作为一个整体完整地消息被发送出去。

4、为什么 TCP 每次建立连接时,初始化序列号都要不一样呢?

答:主要原因是为了防止历史报文被下一个相同四元组的连接接收。

5、已经建立的 TCP 连接,客户端中途宕机,恢复后,向服务端建立连接,此时服务端会怎么处理?

1. 客户端的 SYN 报文里的端口号与历史连接不相同

如果客户端恢复后发送的 SYN 报文中的源端口号跟上一次连接的源端口号不一样,此时服务端会认为是新的连接要建立,于是就会通过三次握手来建立新的连接。

2. 客户端的 SYN 报文里的端口号与历史连接相同

  • 服务端如果收到了客户端的 SYN 报文(注意此时的 SYN 报文其实是乱序的,因为 SYN 报文的初始化序列号其实是一个随机数),会回复一个携带了正确序列号和确认号的 Challenge ACK报文
  • 接着,客户端收到这个 Challenge ACK,发现序列号并不是自己期望收到的,于是就会回 RST 报文,服务端收到后,就会释放掉该连接。

6.如何关闭一个TCP连接?

7、在FIN_WAIT_2 状态时,收到对方发来的数据,但是由于网络延迟,导致对方的FIN先到达,此时接收方是否会在接收FIN报文后直接进入TIME_WAIT 状态

在 FIN_WAIT_2 状态时,如果收到乱序的 FIN 报文,那么就被会加入到「乱序队列」,并不会进入到 TIME_WAIT 状态。

再次收到前面被网络延迟的数据包时,会判断乱序队列有没有数据,然后会检测乱序队列中是否有可用的数据,如果能在乱序队列中找到与当前报文的序列号保持的顺序的报文,就会看该报文是否有 FIN 标志,如果发现有 FIN 标志,这时才会进入 TIME_WAIT 状态。

8、服务器端在 TIME_WAIT 状态的 TCP 连接,收到 SYN 后会发生什么?

 针对这个问题,关键是要看 SYN 的「序列号和时间戳」是否合法

「合法」的 SYN?

  • 合法 SYN:客户端的 SYN 的「序列号」比服务端「期望下一个收到的序列号」要大,并且 SYN 的「时间戳」比服务端「最后收到的报文的时间戳」要大。
  • 非法 SYN:客户端的 SYN 的「序列号」比服务端「期望下一个收到的序列号」要小,或者 SYN 的「时间戳」比服务端「最后收到的报文的时间戳」要小。

如果处于 TIME_WAIT 状态的连接收到「合法的 SYN 」后,就会重用此四元组连接,跳过 2MSL 而转变为 SYN_RECV 状态,接着就能进行建立连接过程

如果处于 TIME_WAIT 状态的连接收到「非法的 SYN 」后,就会再回复一个第四次挥手的 ACK 报文,客户端收到后,发现并不是自己期望收到确认号(ack num),就回 RST 报文给服务端

 

9、TCP 的数据报文具体重传几次呢?

1. TCP keepaliveTCP 层(内核态) 实现的,在 Linux 系统中,提供了一个叫 tcp_retries2 配置项,默认值是 15,不过 tcp_retries2 设置了 15 次,并不代表 TCP 超时重传了 15 次才会通知应用程序终止该 TCP 连接内核会根据 tcp_retries2 设置的值,计算出一个 timeout如果重传间隔超过这个 timeout,则认为超过了阈值,就会停止重传,然后就会断开 TCP 连接。

2. TCP数据包最大重传次数由tcp_syn_retries内核参数控制,这个参数是可以自定义的,默认值一般是 5。通常,第一次超时重传是在 1 秒后,第二次超时重传是在 2 秒,第三次超时重传是在 4 秒后,第四次超时重传是在 8 秒后,第五次是在超时重传 16 秒后。没错,每次超时的时间是上一次的 2 倍。所以,总耗时是 1+2+4+8+16+32=63 秒,大约 1 分钟左右。当第五次超时重传后,会继续等待 32 秒,如果服务端仍然没有回应 ACK,客户端就不再发送 SYN 包,然后断开 TCP 连接。

10、当网线拔掉后,再重新连接,客户端的IP地址和端口会重新随机生成嘛?

除非切换了网络,否则IP地址和端口不会重新随机生成。下面是对客户端获取IP地址的介绍:

DHCP 客户端进程监听的是 68 端口号DHCP 服务端进程监听的是 67 端口号。DHCP 交互中,全程都是使用 UDP 广播通信

  • 客户端首先发起 DHCP 发现报文(DHCP DISCOVER) 的 IP 数据报,由于客户端没有 IP 地址,也不知道 DHCP 服务器的地址,所以使用的是 UDP 广播通信其使用的广播目的地址是 255.255.255.255(端口 67) 并且使用 0.0.0.0(端口 68) 作为源 IP 地址DHCP 客户端将该 IP 数据报传递给链路层,链路层然后将帧广播到所有的网络中设备。
  • DHCP 服务器收到 DHCP 发现报文时,用 DHCP 提供报文(DHCP OFFER) 向客户端做出响应。该报文仍然使用 IP 广播地址 255.255.255.255,该报文信息携带服务器提供可租约的 IP 地址子网掩码默认网关DNS 服务器以及 IP 地址租用期
  • 客户端收到一个或多个服务器的 DHCP 提供报文后,从中选择一个服务器,并向选中的服务器发送 DHCP 请求报文进行响应回显配置的参数
  • 最后,服务端用 DHCP ACK 报文对 DHCP 请求报文进行响应应答所要求的参数

租约的 DHCP IP 地址快到期后,客户端会向服务器发送 DHCP 请求报文:

  • 服务器如果同意继续租用,则用 DHCP ACK 报文进行应答,客户端就会延长租期。
  • 服务器如果不同意继续租用,则用 DHCP NACK 报文,客户端就要停止使用租约的 IP 地址。

11、有哪些用于防御SYN攻击的方法?

  • 减少超时重传次数;
  • 增大半连接队列;
  • 开启tcp_syncookies功能;

12、延迟确认和Nagle算法混合使用会产生说明问题?

当我们 TCP 报文的承载的数据非常小时,整个网络的效率很低。那么就出现了常见的两种策略,来减少小报文的传输,分别是:

  • Nagle 算法
  • 延迟确认

Nagle 算法的思路是只有满足下面两个条件中的任意一个条件,才能可以发送数据:

  • 条件一:要等到窗口大小 >= MSS 并且 数据大小 >= MSS
  • 条件二:收到之前发送数据的 ack 回包;

Nagle 算法一定会有一个小报文,也就是在最开始的时候。

TCP 延迟确认的策略

  • 有响应数据要发送时,ACK 会随着响应数据一起立刻发送给对方;
  • 没有响应数据要发送时,ACK 将会延迟一段时间,以等待是否有响应数据可以一起发送;
  • 如果在延迟等待发送 ACK 期间,对方的第二个数据报文又到达了,这时就会立刻发送 ACK

发送方使用了 Nagle 算法接收方使用了 TCP 延迟确认会发生如下的过程:

  • 发送方先发出一个小报文,接收方收到后,由于延迟确认机制,自己又没有要发送的数据,只能干等着发送方的下一个报文到达;
  • 而发送方由于 Nagle 算法机制,在未收到第一个报文的确认前,是不会发送后续的数据;
  • 所以接收方只能等待最大时间 200 ms 后,才回 ACK 报文,发送方收到第一个报文的确认报文后,也才可以发送后续的数据。

要解决这个问题,只有两个办法:

  • 要不发送方关闭 Nagle 算法
  • 要不接收方关闭 TCP 延迟确认

13、为什么抓包抓到的TCP挥手是三次,而不是四次?

当被动关闭的一方在接收到主动关闭方发送来的FIN请求后,由于此时被动关闭方没有数据需要发送,且开启了TCP延迟确认机制。使得针对主动关闭方发送来的FIN请求的ACK应答需要和被动关闭方的FIN请求一同发送。所以四次挥手变成了三次。

14、为什么TCP握手是三次不是二次或四次

不使用「两次握手」和「四次握手」的原因:

  • 「两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
  • 「四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。

原因一:避免历史连接
如果是两次握手连接,就无法阻止历史连接
主要是因为在两次握手的情况下,「被动发起方」没有中间状态给「主动发起方」来阻止历史连接,导致「被动发起方」可能建立一个历史连接,造成资源浪费

 原因二:同步双方初始序列号

 四次握手其实也能够可靠的同步双方的初始化序号,但由于第二步和第三步可以优化成一步,所以就成了「三次握手」。

15、如何解决糊涂窗口综合征?

如果接收方太忙了,来不及取走接收窗口里的数据,那么就会导致发送方的发送窗口越来越小。到最后,如果接收方腾出几个字节并告诉发送方现在有几个字节的窗口,而发送方会义无反顾地发送这几个字节,这就是糊涂窗口综合症

解决糊涂窗口综合症,就要同时解决以下两个问题:

  • 让接收方不通告小窗口给发送方
  • 让发送方避免发送小数据

接收方策略:

  • 当窗口大小<min( MSS,缓存空间/2 ) ,就会向发送方通告窗口为 0,阻止发送方再发数据过来;
  • 当窗口大小 >=min( MSS,缓存空间/2 ) ,就可以把窗口打开让发送方发送数据过来;

发送方策略:开启Nagle算法。

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

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

经过 TCP 层分片后,如果一个 TCP 分片丢失后,进行重发时也是以 MSS 为单位,而不用重传所有的分片,大大增加了重传的效率。

17、如何计算超时重传时间?

RTT 指的是数据发送时刻到接收到确认的时刻的差值,也就是包的往返时间

超时重传时间是以 RTO (Retransmission Timeout 超时重传时间)表示:

  • 当超时时间 RTO 较大时,重发就慢,丢了老半天才重发,没有效率,性能差;
  • 当超时时间 RTO 较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。

超时重传时间 RTO 的值应该略大于报文往返 RTT 的值

估计往返时间,通常需要采样以下两个:

  • 采样 RTT 的时间,然后进行加权平均,算出一个平滑 RTT 的值。
  • 采样 RTT 的波动范围,这样就避免如果 RTT 有一个大的波动的话,很难被发现的情况。

18、为什么 UDP 头部没有「首部长度」字段,而 TCP 头部有「首部长度」字段呢?

原因是 TCP 有可变长的「选项」字段,而 UDP 头部长度则是不会变化的,无需多一个字段去记录 UDP 的首部长度。

19、为什么 UDP 头部有「包长度」字段,而 TCP 头部则没有「包长度」字段呢?

  • 其中 IP 总长度 和 IP 首部长度,在 IP 首部格式是已知的。TCP 首部长度,则是在 TCP 首部中是已知的,所以就可以求得 TCP 数据的长度。
  • 为了网络设备硬件设计和处理方便,首部长度需要是 4字节的整数倍。如果去掉 UDP 「包长度」字段,那 UDP 首部长度就不是 4 字节的整数倍了
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值