图解 TCP 三次握手与四次挥手

2017-07-12 14:13:56 +08:00
 enocher

引言

TCP 三次握手和四次挥手不管是在开发还是面试中都是一个非常重要的知识点,它是我们优化 web 程序性能的基础。但是大部分教材都对这部分解释的比较抽象,本文我们就利用 wireshark 来抓包以真正体会整个流程的细节。

三次握手

根据下面这幅图我们来看一下 TCP 三次握手。p.s: 每个箭头代表一次握手。

第一次握手

client 发送一个SYN(J)包给 server,然后等待 server 的 ACK 回复,进入SYN-SENT状态。p.s: SYN 为 synchronize 的缩写,ACK 为 acknowledgment 的缩写。

第二次握手

server 接收到 SYN(seq=J)包后就返回一个ACK(J+1)包以及一个自己的**SYN(K)**包,然后等待 client 的 ACK 回复,server 进入SYN-RECIVED状态。

第三次握手

client 接收到 server 发回的 ACK(J+1)包后,进入ESTABLISHED状态。然后根据 server 发来的 SYN(K)包,返回给等待中的 server 一个ACK(K+1)包。等待中的 server 收到 ACK 回复,也把自己的状态设置为ESTABLISHED。到此 TCP 三次握手完成,client 与 server 可以正常进行通信了。

为什么要进行三次握手

我们来看一下为什么需要进行三次握手,两次握手难道不行么?这里我们用一个生活中的具体例子来解释就很好理解了。我们可以将三次握手中的客户端和服务器之间的握手过程比喻成 A 和 B 通信的过程:

wireshark

上面分析还不够形象,很容易忘记,下面我们利用 wireshark 来证明一下上面的分析过程。从下面的的输出就可以很容易看出来,必须要经过前面的三次 tcp 请求才会有起一次 http 请求。

第一次请求客户端发送一个 SYN 包,序列号是 0。

第二次请求服务器会发送一个 SYN 和一个 ACK 包,序列号是 0,ack 号是 1。

第三次本地客户端请求会发送一个 ACK 包,序列号是 1,ack 号是 1 来回复服务器。

四次挥手

以下面这张图为例,我们来分析一下 TCP 四次挥手的过程。

第一次挥手

client 发送一个FIN(M)包,此时 client 进入FIN-WAIT-1状态,这表明 client 已经没有数据要发送了。

第二次挥手

server 收到了 client 发来的 FIN(M)包后,向 client 发回一个ACK(M+1)包,此时 server 进入CLOSE-WAIT状态,client 进入FIN-WAIT-2状态。

第三次挥手

server 向 client 发送FIN(N)包,请求关闭连接,同时 server 进入LAST-ACK状态。

第四次挥手

client 收到 server 发送的 FIN(N)包,进入TIME-WAIT状态。向 server 发送**ACK(N+1)**包,server 收到 client 的 ACK(N+1)包以后,进入CLOSE状态; client 等待一段时间还没有得到回复后判断 server 已正式关闭,进入CLOSE状态。

References

TCP-CONNECTION TCP-TERMINATION

公众号

欢迎大家关注我的公众号ziwenxie_mj订阅我博客上的原创文章 :)

p.s: 如有错误,还望指正 :)

6926 次点击
所在节点    Linux
44 条回复
anxious
2017-07-13 21:45:13 +08:00
@paradoxs 无状态和 keep-alive 其实没有关系,是从两个角度上描述的。

无状态,意思是 HTTP 协议 的前后两次请求,是相互无关的,本次的 HTTP 请求,对上一次的 HTTP 请求没有影响,对下一次的请求没有影响。

keep-alive 可以从 TCP 的长连接,还是短连接 来说。
在 HTTP 早先的版本,默认是 一次 HTTP 请求、响应完成,就断开连接。这就是短连接。

后续因为 server、client 的性能都更好,所以就希望能够长连接,来减少 TCP 建立连接的消耗,所以后面希望推动长连接。
但为了兼容以前短连接的历史原因,如果需要长连接,请明确声明 Keep-alive。
anxious
2017-07-13 21:51:53 +08:00
@suixinqiejing 对于这个的理解,不能站在上帝视角来看,你应该单纯的站在 A 的角度来看。

比如,你就是 A,你给 B 写信,你把信投入了邮筒之后,你怎么确定的知道你的信件送达到了 B ?
就是 B 给你回信,而且内容 与 你寄出去的那一封是相关的。

你这个时候,才能确认 你的信 之前确实到达了 B。
ytlm
2017-07-14 16:07:02 +08:00
@qien http://vcpu.me/TIME_WAIT%E7%8A%B6%E6%80%81%E5%88%86%E6%9E%90/ 这个对 TIME_WAIT 解释的很好,可以看下
ytlm
2017-07-14 16:09:29 +08:00
本质山应该是为了在不可靠的网络上建立可靠的传输通道,三次刚好是一个比较稳妥的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/374778

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX