TCP三次握手和四次挥手的解释

news/2025/3/15 1:16:21/

基础知识

在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG.

其中,对于我们日常的分析有用的就是前面的五个字段。

它们的含义是:

SYN表示建立连接(synchronous建立联机)FIN表示关闭连接(finish结束) ACK表示响应(acknowledgement 确认) PSH表示DATA数据传输 (push传送)RST表示连接重置(reset重置) 

其中,ACK是可能与SYN,FIN等同时使用的,比如SYN和ACK可能同时为1,它表示的就是建立连接之后的响应,

如果只是单个的一个SYN,它表示的只是建立连接。

TCP的几次握手就是通过这样的ACK表现出来的。

但SYN与FIN是不会同时为1的,因为前者表示的是建立连接,而后者表示的是断开连接。

RST一般是在FIN之后才会出现为1的情况,表示的是连接重置。

一般地,当出现FIN包或RST包时,我们便认为客户端与服务器端断开了连接;而当出现SYN和SYN+ACK包时,我们认为客户端与服务器建立了一个连接。

PSH为1的情况,一般只出现在 DATA内容不为0的包中,也就是说PSH为1表示的是有真正的TCP数据包内容被传递。

TCP的连接建立和连接关闭,都是通过请求-响应的模式完成的。

TCP三次握手

TCP(Transmission Control Protocol)传输控制协议

TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:
三次握手连接

  1. 客户端 A 发送 SYN 包(SYN=j)到服务器 B,并进入SYN_SEND 状态,等待服务器 B 确认。

  2. 服务器 B 收到 SYN 包,必须确认客户 A 的 SYN(ACK=j+1),同时自己也发送一个 SYN 包(SYN=k),即 ACK+SYN 包,此时服务器 B 进入SYN_RECV 状态。

  3. 客户端 A 收到服务器 B 的 SYN+ACK 包,向服务器 B 发送确认包 ACK(ACK=k+1)。此包发送完毕,客户端 A 和服务器 B 进入 ESTABLISHED 状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据。

TCP四次挥手

由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。

这个原则是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向的连接。

收到一个 FIN 只意味着这一方向上没有数据流动,一个 TCP 连接在收到一个 FIN 后仍能发送数据。

首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

TCP采用四次挥手关闭连接如图所示。
这里写图片描述

  1. 客户端 A 发送一个 FIN,用来关闭客户 A 到服务器 B 的数据传送。

  2. 服务器 B 收到这个 FIN,它发回一个 ACK,确认序号为收到的序号加1。和 SYN 一样,一个 FIN 将占用一个序号。

  3. 服务器 B 关闭与客户端 A 的连接,发送一个 FIN 给客户端 A。

  4. 客户端 A 发回 ACK 报文确认,并将确认序号设置为收到序号加1。

在linux中进行socket编程过程

这里写图片描述

CLOSED: 这个没什么好说的了,表示初始状态。LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本 上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状 态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。ESTABLISHED: 这个容易理解了,表示连接已经建立了。FIN_WAIT_1(重要): 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别 是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即 进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。 FIN_WAIT_2(重要): 上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。 TIME_WAIT(重要、共详细的请看下图的2MSL): 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带 FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。 CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。 CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。 LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

参考链接:
https://blog.csdn.net/phunxm/article/details/5085792
https://blog.csdn.net/lqglqglqg/article/details/48714611
https://blog.csdn.net/fadefaraway/article/details/54633278 网络——TCP状态转换图、滑动窗口、半连接状态、2MSL


http://www.ppmy.cn/news/603918.html

相关文章

go未入门学习记录

go未入门学习记录 开发环境配置go1.12.17goland 参考链接macos配置go语言以及goland开发环境 语法学习记录 package main //kaiyu.liushopee.com golang学习笔记 //参考资料 https://www.kancloud.cn/itfanr/go-quick-learn/81636 //参考视频 https://www.bilibili.com/v…

IOS自动化测试环境搭建(Python Java)

一、前言 IOS的App自动化测试与Android的一样,也可以用appium来进行。但是IOS自动化依赖苹果的osx系统、Xcode构建等,且封闭的系统需要苹果开发者账号才可以驱动真机。Appium的环境配置有点麻烦,可能大部分时间都在处理各种稀奇古怪的报错&am…

linux 下根据cpp文件快速书写头文件

假设我们现在有一个hello.cc文件,我们如果想要书写它的头文件hello.h,使用如下的命令即可: cat hello.cc | grep "^\w.*)$" > hello.h 然后我们在hello.h中添加我们依赖的头文件即可

docker 常用命令集合

查看images docker images 查看container docker ps docker container ps -a 启动container docker container start ##### 暂停container docker container stop ##### 删除container docker container rm ###### 连接container docker attach ####

macos新版本docker换源方法

#macos新版docker换源方法

mac git使用与配置踩过的坑

#mac git使用与配置踩过的坑 标题mac配置git ssh密钥 参考链接mac配置git ssh key go get安装失败的解决方法 go get约等于git clonego install,下载安装git仓代码时报错fatal: could not read Username … terminal prompts disabled。解决方法: 方…

python 实现桶排序

前言 桶排序(Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里。每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的…