TCP 协议中的三次握手和四次挥手

马谦马谦马谦 TCP/IP评论469字数 1632阅读 5 分 26 秒阅读模式

一、三次握手

TCP 协议的三次握手和四次挥手分别表示了 TCP 连接的建立和释放过程,在整个 TCP 协议是一个很重要的内容,同时也是面试时的常见考点。

趁着找工作的劲,使用 socket+tcpdump 分析了一下工作流程,socket 客户端代可以在 socket 介绍及函数原语找到。服务端的代码可以在 socket 的 select 模型找到。

socket 中各函数对应的 TCP 状态演示图:

TCP协议中的三次握手和四次挥手-图片1

三次握手的流程可以形容为 (摘取自 《TCP/IP 协议:卷一》):

  1. 请求端 (通常称为客户) 发送一个 SYN 段指明客户打算连接的服务器的端口,以及初始序号 (ISN),这个 SYN 段为报文段 1 。
  2. 服务器发回包含服务器的初始序号的 SYN 报文段 (报文段 2) 作为应答。同时,将确认序号设置为客户的 ISN 加 1 以对客户的 SYN 报文段进行确认,一个 SYN 将占用一个序号。
  3. 客户必须将确认序号设置为服务器的 ISN 加 1 以对服务器的 SYN 报文段进行确认 (报文段 3) 。

图片流程:

TCP协议中的三次握手和四次挥手-图片2

测试

开始 tcpdump 开始抓包:

开启另外一个终端打开服务端:

再开启一个终端开启客户端:

此时 tcpdump 的输出为:

这三个数据包验证了三次握手的流程:

第一个可以看出是客户端 33632 发给服务端 9999 的数据包,是一个 SYN 数据包,seq2197027846

第二个数据包为服务端返回的 ACK 数据包,ack=2197027847,等于上一个数据包中客户端的 seq+1

第三个数据包是客户端给服务端的,它也带了 ack,并且等于上一个数据包中服务端发过来的 seq+1

此时客户端和服务端的连接状态都到达了 ESTABLISHED

二、四次挥手

四次挥手是由 TCP 的半关闭 (half-close) 造成的。既然一个 TCP 连接是全双工 (即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。这原则就是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向连接。当一端收到一个 FIN,它必须通知应用层另一端几经终止了那个方向的数据传送。发送 FIN 通常是应用层进行关闭的结果。

收到一个 FIN 只意味着在这一方向上没有数据流动。一个 TCP 连接在收到一个 FIN 后仍能发送数据。而这对利用半关闭的应用来说是可能的,尽管在实际应用中只有很少的 TCP 应用程序这样做。

通过快捷键 CTRL+C 或者在客户端界面输入 exit 即可退出客户端,退出后的 tcpdump 输出:

四次挥手分析:

第一行客户端发给服务端,是一个 FIN 数据包,表示客户端要结束发送数据。

第二行是服务端的对上一条的响应,ack(3554397809)=seq(3554397808)+1

服务端在收到客户端的关闭消息后也关闭了连接,也发了一个 FIN 数据包,seq=2489855325

客户端收到服务端的关闭消息后也回了一个 ack 数据包,ack(2489855326)=seq(2489855325)+1

三、 2MSL 状态

2MSL 状态是连接断开后需要继续等待的时间,客户端在收到服务端的 FIN 数据包之后,会进入 2MSL 的等待期,在这段时间内,任何来自服务端的数据都会被拒绝。这段时间存在的意义主要有以下几点:

  1. 客户端收到 FIN 后给服务端回 ACK,如果此时数据没有到达服务端,服务端会尝试重连,浪费服务端资源。同时,如果立马又有一个程序占用了这个端口,收到服务端的重传 FIN 之后将会关闭。
  2. 服务端的数据包可能存在时延,一些数据包在 FIN 之后到达客户端,如果客户端关闭之后又起了一个程序,第二个程序将会收到来自前一个业务逻辑的数据,导致错误。

  最后更新:2020-2-21
马谦马谦马谦
  • 本文由 马谦马谦马谦 发表于 2018 年 4 月 9 日 11:11:04
  • 转载请务必保留本文链接:https://www.dyxmq.cn/network/tcpip/the-three-way-handshake-and-four-wave-waving-in-tcp.html
socket多路IO复用之select模型 C/C++

socket 多路 IO 复用之 select 模型

select 模型是 socket 中的一种多路 IO 复用模型之一,通过轮询的方式来完成多路访问控制。 一个很简单的例子来描述 select 模型: 幼儿园老师要照顾所有的小朋友,每天他都会轮流去问小朋友:「小朋...
Wireshark抓取以太网数据包 Wireshark

Wireshark 抓取以太网数据包

一、概述 几乎所有的数据包都是通过以太网来传输,所以使用 wireshark 抓取以太网数据包非常容易,这里我们以 DNS 数据包为例。 二、抓包 1. 准备数据 打开 wireshark,在筛选栏输入 dns,...
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证