miller
发布于

回顾: 熟悉 HTTP,TCP/IP

原文地址 www.zhihu.com

TCP 的定义

TCP 全称为 Transmission Control Protocol(传输控制协议),是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP 是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。

TCP 的三次握手和四次挥手,可以说是老生常谈的经典问题了,通常也作为各大公司常见的面试考题,具有一定的水平区分度。看似简单的面试问题。如果你的回答不符合面试官期待的水准,有可能就直接凉凉了。

本文会围绕,从三次握手和四次挥手相关的一系列核心问题,分享如何更准确回答和应对常见的面试问题,以后面对再刁钻的面试官,你都可以随意地跟他扯皮了

优雅回答三次握手

三次握手:服务端新建套接字,绑定地址信息后开始监听,进入 LISTEN 状态。客户端新建套接字绑定地址信息后调用 connect,发送连接请求 SYN,并进入 SYN_SENT 状态,等待服务器的确认。服务端一旦监听到连接请求,就会将连接放入内核等待队列中,并向客户端发送 SYN 和确认报文段 ACK,进入 SYN_RECD 状态。客户端收到 SYN+ACK 报文后向服务端发送确认报文段 ACK,并进入 ESTABLISHED 状态,开始读写数据。服务端一旦收到客户端的确认报文,就进入 ESTABLISHED 状态,就可以进行读写数据了

为什么握手是三次,而不是两次或者四次?

答:两次不安全,四次没必要。tcp 通信需要确保双方都具有数据收发的能力,得到 ACK 响应则认为对方具有数据收发的能力,因此双方都要发送 SYN 确保对方具有通信的能力。第一次握手是客户端发送 SYN,服务端接收,服务端得出客户端的发送能力和服务端的接收能力都正常;第二次握手是服务端发送 SYN+ACK,客户端接收,客户端得出客户端发送接收能力正常,服务端发送接收能力也都正常,但是此时服务器并不能确认客户端的接收能力是否正常;第三次握手客户端发送 ACK,服务器接收,服务端才能得出客户端发送接收能力正常,服务端自己发送接收能力也都正常。

三次握手可以携带数据吗?

答:第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。假设第一次可以携带数据,如果有人恶意攻击服务器,每次都在第一次握手中的 SYN 报文放入大量数据,重复发送大量 SYN 报文,此时服务器会花费大量内存空间来缓冲这些报文,服务器就更容易被攻击了

tcp 三次握手失败,服务端会如何处理?

答:握手失败的原因有两种,第一种是服务端没有收到 SYN,则什么都不做;第二种是服务端回复了 SYN+ACK 后,长时间没有收到 ACK 响应,则超时后就会发送 RST 重置连接报文,释放资源

ISN 代表什么?意义何在?ISN 是固定不变的吗?ISN 为何要动态随机

答:ISN 全称是 Initial Sequence Number,是 TCP 发送方的字节数据编号的原点,告诉对方我要开始发送数据的初始化序列号。ISN 如果是固定的,攻击者很容易猜出后序的确认号,为了安全起见,避免被第三方猜到从而发送伪造的 RST 报文,因此 ISN 是动态生成的

什么是半连接队列

答:服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RECD 状态,此时双方还没有完全建立连接。服务器会把这种状态下的请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起来连接的就会放在全连接队列中,如果队列满了就有可能出现丢包现象

优雅回答四次挥手

四次挥手:客户端主动调用 close 时,向服务端发送结束报文段 FIN 报,同时进入 FIN_WAIT1 状态;服务器会收到结束报文段 FIN 报,服务器返回确认报文段 ACK 并进入 CLOSE_WAIT 状态,此时如果服务端有数据要发送的话,客户端依然需要接收。客户端收到服务器对结束报文段的确认,就会进入到 FIN_WAIT2 状态,开始等待服务器的结束报文段;服务器端数据发送完毕后,当服务器真正调用 close 关闭连接时,会向客户端发送结束报文段 FIN 包,此时服务器进入 LAST_ACK 状态,等待最后一个 ACK 的带来;客户端收到服务器发来的结束报文段, 进入 TIME_WAIT, 并发出送确认报文段 ACK;服务器收到了对结束报文段确认的 ACK,进入 CLOSED 状态,断开连接。而客户端要等待 2MSL 的时间,才会进入到 CLOSED 状态

为什么握手是三次,而挥手时需要四次呢?

答:其实在 TCP 握手的时候,接收端将 SYN 包和 ACK 确认包合并到一个包中发送的,所以减少了一次包的发送。对于四次挥手,由于 TCP 是全双工通信,主动关闭方发送 FIN 请求不代表完全断开连接,只能表示主动关闭方不再发送数据了。而接收方可能还要发送数据,就不能立即关闭服务器端到客户端的数据通道,所以就不能将服务端的 FIN 包和对客户端的 ACK 包合并发送,只能先确认 ACK,等服务器无需发送数据时在发送 FIN 包,所以四次挥手时需要四次数据包的交互

TIME_WAIT 状态有什么作用,为什么主动关闭方没有直接进入 CLOSED 状态释放资源?

答:如果主动关闭方进入 CLOSED 状态后,被动关闭方发送 FIN 包后没有得到 ACK 确认,超时后就会重传一个 FIN 包。如果客户端没有 TIME_WAIT 状态而直接进入 CLOSED 状态释放资源,下次启动新的客户端就可能使用了与之前客户端相同的地址信息,有两个危害,第一种是这个刚启动的新的客户端绑定地址成功时,就会收到了一个重传的 FIN 包,对新连接就会造成影响。第二种是如果该新客户端向相同的服务端发送 SYN 连接请求,但是此时服务端处于 LAST_ACK 状态,要求收到的是 ACK 而不是 SYN,因此就会发送 RST 重新建立请求。

为什么 TIME_WAIT 状态需要经过 2MSL 才能进入 CLOASE 状态?

答:MSL 指的是报文在网络中最大生存时间。在客户端发送对服务端的 FIN 确认包 ACK 后,这个 ACK 包有可能到达不了,服务器端如果接收不到 ACK 包就会重新发送 FIN 包。所以客户端发送 ACK 后需要留出 2MSL 时间(ACK 到达服务器器 + 服务器发送 FIN 重传包,一来一回)等待确认服务器端缺失收到了 ACK 包。也就是说客户端如果等待 2MSL 时间也没收到服务器端重传的 FIN 包,则就可以确认服务器已经收到客户端发送的 ACK 包

一台主机上出现大量的 TIME_WAIT 是什么原因?应该如何处理?

答:TIME_WAIT 是主动关闭方出现的,一台主机出现大量的 TIME_WAIT 证明这台主机上发起大量的主动关闭连接。常见于一些爬虫服务器。这时候我们应该调整 TIME_WAIT 的等待时间,或者开启套接字地址重用选项

一台主机上出现大量的 CLOSE_WAIT 是什么原因?应该如何处理?

答:CLOSE_WAIT 是被动关闭方收到 FIN 请求进行回复之后的状态,等待上层程序进一步处理,若出现大量 CLOSE_WAIT,有可能是被动关闭方主机程序中忘了最后一步断开连接后调用 close 释放资源。这是一个 BUG.,只需要加上对应的 close 即可解决问题

tcp 连接管理中的保活机制

答:tcp 通信中,若两端长时间没有数据往来,则这时候每隔一段时间,服务端会向客户端发送一个保活探测数据报,要求客户端进行回复。若连续多次没有收到响应,就认为连接已经断开。长时间默认为 7200s,每隔一段时间默认为 75s,连续多次无响应默认为 9 次。这些数据都可以在套接字中修改,接口:Setsockopt

浏览 (1411)
点赞
收藏
评论