likes
comments
collection
share

前端面试必聊的TCP四次挥手断开,是由客户端发起的吗?

作者站长头像
站长
· 阅读数 3

先歪一个题,在前一篇文章中,有个兄弟评论说,现在确实没什么技术方向可写了....

前端面试必聊的TCP四次挥手断开,是由客户端发起的吗?

这里想说的是,技术文章的细节点很多,不管是最新的、老掉牙的、还是策略的,大牛多的很呐! 我自己写这些玩意,大部分是觉的有意思,好玩了,才会有动力去写,加上也是才疏学浅,不一定写的好,写的要是博君一哂,也算值了~

前端面试必聊的TCP四次挥手断开,是由客户端发起的吗?

好了,进入主题。这次写文章的缘由,主要在聊天时,谈到【从输入URL到浏览器渲染页面】这个历程中,突然意识到,服务端是没法知道客户端到底还需不需要通信的,那么,客户端需要怎么判断自己不再需要TCP通道了呢?

进而再发散下,到底是不是客户端判断呢?还是服务端自行等待一段时间,直接断开连接呢?

如果以上问题都有答案,那么确实不再需要看下去了,咱欢送大佬~~

前端面试必聊的TCP四次挥手断开,是由客户端发起的吗?

如果看到这了,那么就一起聊聊,以下常规的四次挥手描述的,(我摘抄的):

当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手。

  • 发起方向被动方发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态。(第一次挥手:由浏览器发起的,发送给服务器,我请求报文发送完了,你准备关闭吧)
  • 被动方发送报文,Ack、Seq,表示同意关闭请求。此时主机发起方进入 FIN_WAIT_2 状态。(第二次挥手:由服务器发起的,告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧)
  • 被动方向发起方发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。(第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完了,你准备关闭吧)
  • 发起方向被动方发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间未收到回复,则正常关闭。(第四次挥手:由浏览器发起,告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧)

如果以上描述是对的,那么客户端是如何去判断自己还需不需要连接通信呢?能想到的就是要么设定一个固定通信时长,加上一个【无限续杯】方法,即规定时间内再次有通信,则将通信时长重新计时。

那么问题来了,如果将通信时长设置完全交给客户端,会有很大问题。主要在于,服务端会面对很多很多个客户端,而客户端通常只和几个服务端通信,如果服务端在通信时,只要碰到一个胡搅蛮缠的客户端,将其通信时长设定在1W年,那服务端就得抓瞎。

所以,最大可能是服务端去设定他与这个客户端通信时长。

以上都是猜想,对于已经知道答案的大佬或者后端看到这,就更会觉的可笑。

实际情况如何呢?我先找到权威书籍## 《TCP/IP详解》,翻到章节 13.2 TCP连接的建立与终止~

前端面试必聊的TCP四次挥手断开,是由客户端发起的吗?

TCP协议中描述了双方关闭的情况处理,我认为这个就说明,客户端和服务端双方都可以主动发起请求,来关闭TCP通信通道的,接下来,我就说说我理解的,欢迎拍砖:

首先很早期,如HTTP 1.0时,每一次HTTP请求后,服务端完成资源传输后,双方即开始关闭TCP通信通道,很浪费资源,对吧?这个也被称为短连接

前端面试必聊的TCP四次挥手断开,是由客户端发起的吗?

短连接显然不符合web的可持续发展,为了优化这个情况,可以使用HTTP互通请求中的一个字段,Connection: keep-alive,可以使用同一个 TCP 连接来发送和接收多个 HTTP 请求/应答,避免了连接建立和释放的开销,这个也称为长连接。现代浏览器中,基本都是HTTP 1.1,默认会开启这个。

长连接的效果有用,必须是两个端都要开启才行。而且为了避免某些客户端占着茅坑不拉屎一直不请求的情况,web 服务软件一般都会提供 keepalive_timeout 参数,用来指定 HTTP 长连接的超时时间。

以上就说明,客户端可以发起关闭请求的时机有两个:

1、未开启长连接时,完成接收资源后;

2、开启长连接,通信时长超出后;

但问题来了,到底是客户端还是服务端主动关闭连接呢?

在 RFC 文档中,并没有明确由谁来关闭连接,请求和响应的双方都可以主动关闭 TCP 连接。

不过,根据大多数 Web 服务的实现,不管哪一方禁用了 HTTP Keep-Alive,都是由服务端主动关闭连接,那么此时服务端上就会出现 TIME_WAIT 状态的连接。出现这个状态,服务端不会再发送数据,但可以接受请求。

还有一个情况,受服务端的资源限制,单个长连接,不可能处理无限个HTTP请求,所以,如果单个长连接超过服务端设置的可处理数量,服务端也会主动关闭掉这个长连接,当然,状态依旧是TIME_WAIT

几点细节

至此,应该大致都明白了吧欢迎大佬指点