Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

技术 / 网络 / 理解TCP三次握手和四次挥手 #26

Open
huanzhiyazi opened this issue Nov 6, 2020 · 0 comments
Open

技术 / 网络 / 理解TCP三次握手和四次挥手 #26

huanzhiyazi opened this issue Nov 6, 2020 · 0 comments
Labels
documentation Improvements or additions to documentation

Comments

@huanzhiyazi
Copy link
Owner

目录



1 三次握手建立连接[Top]

关于 TCP 为什么需要三次握手建立连接、四次挥手断开连接,网上有很多标准的答案,很多讲的都非常不错。这里总结一下三次握手四次挥手中我认为最能帮助理解的原因分析。

先看一下三次握手建立连接的图示:

TCP connect

为什么需要三次握手呢?关键的原因是 通信双方为了相互确认对方收发信息的能力都是正常的。这也是 TCP 建立连接的目的。具体而言:

  1. 客户端先向服务器发送 SYN 报文,如果服务器收到之后,便能确认客户端发送信息能力正常,但此时还不确定客户端接收信息能力是否正常。
  2. 然后,服务器返回给客户端 SYN+ACK 报文,SYN 使得客户端确认服务器发送信息能力正常,ACK 使得客户端确认服务器接收信息能力正常,因为这个 ACK 是服务器对上一步客户端发送 SYN 的一个确认。到这里,客户端已经完全确认了服务器收发信息都是正常的。
  3. 客户端最后再回复一个 ACK 报文给服务器,作为上一步服务器发送给客户端的 SYN 的一个确认。服务器收到该 ACK 之后便终于确认客户端接收信息的能力也是正常的。到这里,服务器已经完全确认了客户端收发信息都是正常的。

所以,经过以上三步,客户端和服务器都完全确认对方收发信息的能力都是正常的,连接建立成功,可以正常传输数据了。



2 四次挥手断开连接[Top]

先看一下四次挥手断开连接的图示:

TCP disconnect

需要四次挥手断开连接的关键原因是,通信双方为了相互确认对方不再发送数据给自己了。为什么只需要确认不再发送信息而不需要确认接收信息呢?因为接收信息是对方自己可以完全处理的事情,不需要自己关心,而对方如果还需要发送信息,那必须等待对方发完,否则最终自己接收到的信息可能就是不完整的。

具体而言:

  1. 客户端首先执行系统调用 close() 关闭连接,向服务器发送 FIN 报文。这时客户端不再发送数据,只读取未读完的缓存数据。服务器收到 FIN 报文,便确认客户端已经不再发送数据过来了。客户端接下来需要确认服务器不再发送数据了,等待服务器发送 FIN 报文过来,进入 <FIN_WAIT1> 状态。
  2. 服务器向客户端发送 ACK 报文,告诉客户端我已经知道你不再发送数据过来了,但服务器可能还有数据没有发送完,所以这一步只向客户端发送 ACK 确认报文,而不捎带 FIN。客户端知道服务器已经知道自己不再发送数据了,但是服务器仍然需要时间处理完未发完的数据,所以仍然需要等待服务器发送 FIN 过来,进入 <FIN_WAIT2> 状态,即等待服务器 FIN 报文过来的第二个阶段。
  3. 服务器发送完所有数据后,执行系统调用 close(),并向客户端发送 FIN 报文,告诉客户端,我也不再发送数据了。但是服务器仍然需要确认客户端已经知道自己不再发送数据,所以进入 <LAST_ACK> 状态,即等待最后确认状态。
  4. 客户端收到来自服务器的 FIN 报文,知道服务器也不再发送数据了,于是进入 <TIME_WAIT> 状态,在这个状态下,需要等待 2MSL 时间(2个最大报文生存时间)后最终进入 <CLOSE> 状态。同时向服务器发送最后一个 ACK 确认报文。

为什么客户端最后需要在 <TIME_WAIT> 状态等待 2MSL 的时间呢?因为网络是不可靠的,最后一个 ACK 报文可能丢失到不了服务器。服务器在发送完最后一个 FIN 之后,如果在超时时间内没有收到客户端的 ACK,会重发一次 FIN 给客户端,客户端会再重发一个 ACK 报文并重新计时。如果客户端不等待 2MSL 直接进入关闭状态,那么服务器可能永远收不到最后的 ACK 报文了,也就无法进入关闭状态了。

@huanzhiyazi huanzhiyazi added the documentation Improvements or additions to documentation label Nov 6, 2020
@huanzhiyazi huanzhiyazi changed the title 理解TCP三次握手和四次挥手 技术 / 网络 / 理解TCP三次握手和四次挥手 Nov 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

1 participant