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 来证明一下上面的分析过程。从下面的的输出就可以很容易看出来,必须要经过前面的三次 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状态。
TCP-CONNECTION TCP-TERMINATION
欢迎大家关注我的公众号ziwenxie_mj订阅我博客上的原创文章 :)
p.s: 如有错误,还望指正 :)
|  |      1est      2017-07-12 14:17:51 +08:00 LZ 放心。在公众号写技术文章没人看的。 | 
|      3SKull4      2017-07-12 14:58:21 +08:00 每次握手,回首出现了问题会怎样 | 
|      4zealot0630      2017-07-12 16:56:32 +08:00 "为什么要进行三次握手" 这个问题回答到并不好 我只能给 4/10 分 | 
|      5zealot0630      2017-07-12 16:58:33 +08:00 三次握手其中一个功能是防 DDOS,先领会到这里能拿及格分 | 
|  |      6ibufu      2017-07-12 17:02:13 +08:00 还以为是来讲笑话的 | 
|      7enocher OP @SKull4 以第三次客户端没有发送给服务器 ack 请求为例子,这里涉及到超时和重传机制,这个时候服务器没法进入 ESTABLISHED 状态,如果超过一定时间服务器后向客户端发送 RTS 报文,同时进入 CLOSED 状态。深入一点也可以去了解一下 syn 攻击之类的 :) | 
|  |      8ajan      2017-07-12 17:18:04 +08:00 完全没有在微信里看文章的癖好~ | 
|  |      9Geoion      2017-07-12 17:20:13 +08:00  2 没人会在公众号看技术文章的,据我观察在朋友圈转发技术文章的,都是没有女朋友的。 | 
|  |      10araraloren      2017-07-12 17:24:45 +08:00 | 
|  |      11Chingim      2017-07-12 17:37:27 +08:00 via Android @zealot0630 如何防 ddos,期待展开 | 
|      12woshixiaohao1982      2017-07-12 17:42:18 +08:00 @zealot0630 #5 ddos 实际上 根本防不了,链路层上 就打垮你了 | 
|      13panda1001      2017-07-12 17:49:56 +08:00 via Android | 
|  |      14andyL      2017-07-12 18:01:03 +08:00 Mark | 
|  |      15andyL      2017-07-12 18:02:12 +08:00 不该 mark 的,直接收藏了。 期待前排大佬能把争论的地方讲具体、讲清晰一点 | 
|  |      16anxious      2017-07-12 18:07:21 +08:00  3 建立连接三次握手,常见的有一个 SYN 攻击。 在三次握手的过程中,server 端会维护一个队列,这个队列中都是 已经向 client 返回 ACK,并等待 client ACK 的请求。 如果 client 在此时恶意的不发送 ACK,而是不停的发送 SYN, 就会导致 SERVER 端 的队列被占满,无法接受正常的 TCP 三次握手请求。 | 
|      17qien      2017-07-12 18:22:10 +08:00 TIME_WAIT 状态是怎样产生的,为什么要这样做? | 
|      19ivechan      2017-07-12 18:37:17 +08:00 为什么要把教科书搬到微信公众号上。。 | 
|      20enocher OP @qien The client waits for a period of time equal to double the maximum segment life (MSL) time, <b>to ensure the ACK it sent was received.</b> | 
|  |      21jtsai      2017-07-12 18:57:37 +08:00 via Android 那什么是 tcp 流 | 
|      22hsmocc      2017-07-12 19:14:36 +08:00 via iPhone 感觉在握手时候应该强调下序列号同步的功能 | 
|      23tempdban      2017-07-12 19:37:39 +08:00 via Android 看了评论舒了一口气 另外楼主这算是翻车么 | 
|  |      24cxbig      2017-07-12 20:04:36 +08:00 老实说,这些贴图质量实在是太土了。下面的 Wireshark 的部分跟本就看不清。 做推广能不能有点诚意。 | 
|  |      25JiPhone      2017-07-12 20:35:48 +08:00 补充一个[wireshark 网络分析]( https://book.douban.com/subject/26268767/),考虑到了 tcp 四次挥手中的 sack 导致的 seq 不一致问题 | 
|  |      26paradoxs      2017-07-12 20:37:33 +08:00 好 我来提个问 | 
|  |      27paradoxs      2017-07-12 20:37:58 +08:00 不小心发出去了。 接上面 HTTP 协议的无状态和 keep alive 的关系是什么 | 
|      28ljy2010a      2017-07-12 20:45:10 +08:00 把时序图 和各个状态放出来吧 | 
|      29netfee      2017-07-12 21:24:44 +08:00 via Android 恩,看着关注了一大堆公众号,不过基本上不会去看。为什么对封闭的微信热情这么高,开放的 Web 不是更好!?感谢楼主科普 | 
|      30ixinshang      2017-07-12 21:34:08 +08:00 via Android 值得看 谢谢 | 
|      31facetest      2017-07-12 21:37:48 +08:00 via Android @zealot0630 建议多看书。 | 
|  |      32zoffy      2017-07-12 22:03:44 +08:00 作为一个 web 开发,平时都是用 http 协议,到底什么情况才需要深入到 tcp/ip 啊?? | 
|      33CRVV      2017-07-12 22:18:29 +08:00 "TCP 三次握手和四次挥手不管是在开发还是面试中都是一个非常重要的知识点,它是我们优化 web 程序性能的基础" 求问如何使用这些知识来优化 web 程序? | 
|      34CRVV      2017-07-12 22:26:58 +08:00 三次握手的作用、带来的问题、问题的解决方案、解决方案仍然存在的问题,全部都在 https://tools.ietf.org/html/rfc7413 里面,讲得很清楚。而且 7413 比 793 短得多,很容易读完 | 
|  |      35Antidictator      2017-07-13 08:09:35 +08:00 via Android @Geoion 我老师经常转,孩子都几个他 | 
|  |      36realfreesky      2017-07-13 08:53:57 +08:00 @qien 因为网络的不可靠性,在客户端发送了 ack 包之后,还需要等待 2ms 才到 closed 状态,因为 ack 包可能丢失,对方会重传 FIN 包,这时候客户端需要重传 | 
|  |      37Mutoo      2017-07-13 10:43:00 +08:00 @zealot0630 三次握手给 DDoS 提供了机会,并不是用来防 DDoS 的。 | 
|  |      38tony1016      2017-07-13 10:56:06 +08:00 还是喜欢这个版本: 你瞅啥 瞅你咋滴 呦,咋俩唠唠 | 
|      39suixinqiejing      2017-07-13 17:36:05 +08:00 萌新 请教。 在第二次通信中,B 向 A 发送信息之后,A 可以确认自己的发信能力和 B 的收信能力没有问题,但是 B 不知道自己的发信能力到底如何,所以就需要第三次通信。 B 向 A 发信息 为什么是确认 A 的发信能力。 | 
|      40suixinqiejing      2017-07-13 17:56:38 +08:00 上一个问题问的犹如智障 ,请无视。 | 
|  |      41anxious      2017-07-13 21:45:13 +08:00  2 @paradoxs 无状态和 keep-alive 其实没有关系,是从两个角度上描述的。 无状态,意思是 HTTP 协议 的前后两次请求,是相互无关的,本次的 HTTP 请求,对上一次的 HTTP 请求没有影响,对下一次的请求没有影响。 keep-alive 可以从 TCP 的长连接,还是短连接 来说。 在 HTTP 早先的版本,默认是 一次 HTTP 请求、响应完成,就断开连接。这就是短连接。 后续因为 server、client 的性能都更好,所以就希望能够长连接,来减少 TCP 建立连接的消耗,所以后面希望推动长连接。 但为了兼容以前短连接的历史原因,如果需要长连接,请明确声明 Keep-alive。 | 
|  |      42anxious      2017-07-13 21:51:53 +08:00 @suixinqiejing 对于这个的理解,不能站在上帝视角来看,你应该单纯的站在 A 的角度来看。 比如,你就是 A,你给 B 写信,你把信投入了邮筒之后,你怎么确定的知道你的信件送达到了 B ? 就是 B 给你回信,而且内容 与 你寄出去的那一封是相关的。 你这个时候,才能确认 你的信 之前确实到达了 B。 | 
|      43ytlm      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 解释的很好,可以看下 | 
|      44ytlm      2017-07-14 16:09:29 +08:00 本质山应该是为了在不可靠的网络上建立可靠的传输通道,三次刚好是一个比较稳妥的 |