[转帖]抓包分析 TCP 握手和挥手

分析,tcp,握手,挥手 · 浏览次数 : 0

小编点评

**内容摘要** 本文通过 Wireshark 抓包分析了 TCP 三次握手和四次挥手过程,并解释了它们之间的区别。 **三次握手** 1. 客户端发送 SYN 协议请求。 2. 服务器收到 SYN 消息后,回复 SYN + ACK,确认收到了客户端的 SYN 消息。 3. 客户端收到 SYN + ACK 后,回复 ACK,确认收到了服务器的 SYN 消息。 **四次挥手** 1. 客户端主动发送 FIN 协议请求。 2. 服务器收到 FIN 消息后,回复 ACK,表示已收到客户端的 FIN 消息。 3. 服务器发送 FIN 协议请求,表示准备关闭连接。 4. 客户端收到 FIN 协议请求后,回复 ACK,表示同意关闭连接。 **其他** * TCP 是一个可靠传输协议,其所有特性最终都是为了实现可靠传输服务的。 * 三次握手和四次挥手是 TCP 建立连接的核心步骤。 * 四次挥手是在关闭浏览器页面时发生的第四次挥手过程。 * TIME_WAIT 状态是 TCP 连接关闭时出现的特殊状态,其最长时间是 2 倍。

正文

https://segmentfault.com/a/1190000042750447

 

前言

首先需要明确的是 TCP 是一个可靠传输协议,它的所有特点最终都是为了这个可靠传输服务。在网上看到过很多文章讲 TCP 连接的三次握手和断开连接的四次挥手,但是都太过于理论,看完感觉总是似懂非懂。反复思考过后,觉得我自己还是偏工程型的人,要学习这些理论性的知识,最好的方式还是要通过实际案例来理解,这样才会具象深刻。本文通过 Wireshark 抓包来分析 TCP 三次握手四次挥手,如果你也对这些理论感觉似懂非懂,那么强烈建议你也结合抓包实践来强化理解这些理论性的知识。

三次握手

TCP 建立连接的三次握手是连接的双方协商确认一些信息(Sequence number、Maximum Segment Size、Window Size 等),Sequence number 有两个作用:一个是 SYN 标识位为 1 时作为初始序列号(ISN),则实际第一个数据字节的序列号和相应 ACK 中的确认号就是这个序列号加 1;另一个是 SYN 标识位为 0 时,则是当前会话的 segment(传输层叫 segment,网络层叫 packet,数据链路层叫 frame)的第一个数据字节的累积序列号。Maximum Segment Size 简称 MSS,表示最大一个 segment 中能传输的信息(不含 TCP、IP 头部)。Window Size 表示发送方接收窗口的大小。下面看看我在本地访问博客 mghio 的三次握手过程:

three-way-hand-shake.jpg

图中三个小红框表示与服务器建立连接的三次握手。

  1. 第一步,client 端(这个示例也就是浏览器)发送 SYN 到 server 端;
  2. 第二步,server 端收到 SYN 消息后,回复 SYN + ACK 到client 端,ACK 表示已经收到了 client 的 SYN 消息;
  3. 第三步,client 端收到回复 SYN + ACK 后,也回复一个 ACK 表示收到了 server 端的 SYN + ACK 了,其实

到这一步,client 端的 60469 端口已经是 ESTABLISHED 状态了。
可以看到,其实三次握手的核心目的就是双方互相告知对象自己的 Sequence number,蓝框是 client 端的初始 Sequence number 和 client 端回复的 ACK,绿框是 server 端的初始 Sequence number 和 client 端回复的 ACK。这样协商好初始 Sequence number 后,发送数据包时发送端就可以判断丢包和进行丢包重传了。

三次握手还有一个目的是协商一些信息(上图中黄色方框是 Maximum Segment Size,粉色方框是 Window Size)。

three-way-hand-shake-dg.jpg

到这里,就可以知道平常所说的建立TCP连接本质是为了实现 TCP 可靠传输做的前置准备工作,实际上物理层并没有这个连接在那里。TCP 建立连接之后时拥有和维护一些状态信息,这个状态信息就包含了 Sequence number、MSS、Window Size 等,TCP 握手就是协商出来这些初始值。而这些状态才是我们平时所说的 TCP 连接的本质。因为这个太重要了,我还要再次强调一下,TCP 是一个可靠传输协议,它的所有特点最终都是为了这个可靠传输服务。

四次挥手

下面再来看看,当关闭浏览器页面是发生断开连接的四次挥手过程:

tcp-close-sequence.jpg

相信你已经发现了,上图抓包抓到的不是四次挥手,而是三次挥手,这是为何呢?

这是由于 TCP 的时延机制(因为系统内核并不知道应用能不能立即关闭),当被挥手端(这里是 server 的 443 端口)第一次收到挥手端(这里是 client 的 63612 端口)的 FIN 请求时,并不会立即发送 ACK,而是会经过一段延迟时间后再发送,但是此时被挥手端也没有数据发送,就会向挥手端发送 FIN 请求,这里就可能造成被挥手端发送的 FIN 与 ACK 一起被挥手端收到,导致出现第二、三次挥手合并为一次的现象,也就最终呈现出“三次挥手”的情况。

断开连接四次挥手分为如下四步(假设没有出现挥手合并的情况):

  1. 第一步,client 端主动发送 FIN 包给 server 端;
  2. 第二步,server 端回复 ACK(对应第一步 FIN 包的 ACK)给 client,表示 server 知道 client 端要断开了;
  3. 第三步,server 端发送 FIN 包给 client 端,表示 server 端也没有数据要发送了,可以断开了;
  4. 第四步,client 端回复 ACK 包给 server 端,表示既然双发都已发送 FIN 包表示可以断开,那么就真的断开了啊。

下面是 TCP 连接流转状态图(其中 CLOSED 状态是虚拟的,实际上并不存在),这个图很重要,记住这个图后基本上所有的 TCP 网络问题就可以解决。

tcp_state_diagram.png

其中比较难以理解的是 TIME_WAIT 状态,主动关闭的那一端会经历这个状态。这一端停留在这个状态的最长时间是 Maximum segment lifetime(MSL)的 2 倍,大部分时候被简称之为 2MSL。存在 TIME_WAIT 状态有如下两个原因:

  1. 要可靠的实现 TCP 全双工连接终止;
  2. 让老的重复 segment 在网络中消失(一个 sement 在网络中存活的最长时间为 1 个 MSL,一来一回就是 2 MSL);

为什么握手是三次,而挥手是四次?

嘿嘿,这是个经典的面试题,其实大部分人都背过挥手是四次的原因:因为 TCP 是全双工(双向)的,所以回收需要四次......。但是再反问下:握手也是双向的,但是为什么是只要三次呢?

网上流传的资料都说 TCP 是双向的,所以回收需要四次,但是握手也是双向(握手双方都在告知对方自己的初始 Sequence number),那么为什么就不用四次握手呢?所以凡事需要多问几个为什么,要有探索和怀疑精神。

你再仔细回看上面三次握手的第二步(SYN + ACK),其实是可以拆分为两步的:第一步回复 ACK,第二步再发 SYN 也是完全可以的,只是效率会比较低,这样的话三次握手不也变成四次握手了。

看起来四次挥手主要是收到第一个 FIN 包后单独回复了一个 ACK 包这里多了一次,如果能像握手那样也回复 FIN + ACK 那么四次挥手也就变成三次了。这里再贴一下上面这个挥手的抓包图:

tcp-close-sequence.jpg

这个图中第二个红框就是 server 端回复的 FIN + ACK 包,这样四次挥手变成三次了(如果一个包算一次的话)。这里使用四次挥手原因主要是:被动关闭端在收到 FIN 后,知道主动关闭端要关闭了,然后系统内核层会通知应用层要关闭,此时应用层可能还需要做些关闭前的准备工作,可能还有数据没发送完,所以系统内核先回复一个 ACK 包,然后等应用层准备好了主动调 close 关闭时再发 FIN 包。

而握手过程中就没有这个准备过程了,所以可以立即发送 SYN + ACK(在这里的两步合成一步了,提高效率)。挥手过程中系统内核在收到对方的 FIN 后,只能 ACK,不能主动替应用来 FIN,因为系统内核并不知道应用能不能立即关闭。

总结

TCP 是一个很复杂的协议,为了实现可靠传输以及处理各种网络传输中的 N 多问题,有一些很经典的解决方案,比如其中的网络拥塞控制算法、滑动窗口、数据重传等。强烈建议你去读一下 rfc793 和 TCP/IP 详解 卷1:协议 这本书。

如果你是那些纯看理论就能掌握好一门技能,然后还能举三反一的人,那我很佩服你;如果不是,那么学习理论知识注意要结合实践来强化理解理论,要经过反反复复才能比较好地掌握一个知识,讲究技巧,必要时要学会通过工具来达到目的。

最后 TCP 所有特性基本上核心都是为了实现可靠传输这个目标来服务的,然后有一些是出于优化性能的目的。

与[转帖]抓包分析 TCP 握手和挥手相似的内容:

[转帖]抓包分析 TCP 握手和挥手

https://segmentfault.com/a/1190000042750447 前言 首先需要明确的是 TCP 是一个可靠传输协议,它的所有特点最终都是为了这个可靠传输服务。在网上看到过很多文章讲 TCP 连接的三次握手和断开连接的四次挥手,但是都太过于理论,看完感觉总是似懂非懂。反复思考过

[转帖]tcpdump/wireshark 抓包及分析(2019)

http://arthurchiao.art/blog/tcpdump-practice-zh/ 本文将展示如何使用 tcpdump 抓包,以及如何用 tcpdump 和 wireshark 分析网络流量。 文中的例子比较简单,适合作为入门参考。 1 基础环境准备 为方便大家跟着上手练习,本文将搭建

[转帖]Https、SSL/TLS相关知识及wireShark抓包分析

https://cloud.tencent.com/developer/article/1954070?areaSource=104001.56&traceId=7WZNP412yK3vh7ebw4th0 一、网络通信的三大风险 在HTTP协议中,所有报文的发送、接收都是以明文的形式进行的。也就是说

[转帖]Wireshark:又一个可以查看https消息内容的工具

https://www.jianshu.com/p/7c16474edd9b 我们在接口测试和故障诊断调试时,需要查看消息里边的内容,如果是http消息可以通过wireshark抓包分析软件看到,但https消息内容在传输过程中是加密的,怎样才能看到https加密后的消息呢? 从技术上来说,需要拿到

[转帖]Web技术(七):如何使用并实现MQTT 消息订阅-发布模型?

文章目录 一、什么是发布-订阅消息模型?二、订阅-发布消息模型有哪些应用?2.1 应用于IP 物联网络中的消息传递2.2 应用于操作系统进程间的消息传递2.3 应用于MESH 自组网中的消息传递 三、MQTT 如何实现订阅-发布消息模型?3.1 如何在本机实践MQTT 通信并抓包分析?3.2 MQT

[转帖]Tcpdump抓包命令

tcpdump和ethereal可以用来获取和分析网络通讯活动,他们都是使用libpcap库来捕获网络封包的。 ​在混杂模式下他们可以监控网络适配器的所有通讯活动并捕获网卡所接收的所有帧。 ​要想设置网络接口为混杂模式并执行这些命令来捕获所有的网络封包,需要具有超级用户的权限。 你可以使用这些工具来

[转帖]《Linux性能优化实战》笔记(20)—— 使用 tcpdump 和 Wireshark 分析网络流量

tcpdump 和 Wireshark 是最常用的网络抓包和分析工具,更是分析网络性能必不可少的利器。 tcpdump 仅支持命令行格式使用,常用在服务器中抓取和分析网络包。Wireshark 除了可以抓包,还提供了强大的图形界面和汇总分析工具,在分析复杂的网络情景时,尤为简单和实用。因而,在实际分

[转帖]019 Linux tcpdump 抓包案例入门可真简单啊?

https://my.oschina.net/u/3113381/blog/5477908 1 tcpdump 是什么? tcpdump 可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、端口的过滤,并提供 and、or、not 等逻辑语句来帮助你过滤掉不关注的信息。 通常

[转帖]tcpdump非常实用的抓包实例

https://www.jianshu.com/p/83cf0e64a654 参考资料:http://www.jianshu.com/p/3cca9a74927c <<亲测可用tcpdump查看HTTP流量查看>> 抓包HTTP GET请求: [root@hostname /]# sudo tcpd

[转帖] Linux命令拾遗-网络抓包工具

https://www.cnblogs.com/codelogs/p/16060684.html 简介# Linux中有很多抓包工具,如ngrep、tcpdump与tshark等,它们有很多用法与使用场景,下面我将结合例子讲解各工具的用法以及它们的使用场景。 本系列文章索引Linux命令拾遗-入门篇