网络协议和Netty(6):大白话说四次挥手和用一个数据库关闭连接的例子进行说明

本文主要是介绍网络协议和Netty(6):大白话说四次挥手和用一个数据库关闭连接的例子进行说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:和三次挥手不一样,第一次接触四次挥手的概念的时候,已经有些懵懂,没有再闹出笑话。毕竟经历了“高规格的礼仪”洗礼,有了些警惕性,哈哈。好了不废话了,言归正传。前面说完建立连接时所需要的三次握手的前因后果,这次来说一说,关闭连接时的四次挥手。

 

提问:

什么是四次挥手?

为什么关闭连接时需要四次挥手?

为什么需要TIME_WAIT状态?

拓展:

为什么有时候通过抓包工具查看TCP连接时,发现有时候没有四个数据包?

四次挥手介绍:

概述:

四次挥手就是TCP关闭时,客户端和服务端共发送四次数据包来确认连接的断开。这个发起端即可以是服务端也可以是客户端,调用close方法,发送关闭请求。

第一次挥手

图示

第一次挥手时,客户端应用调用close()方法(注意:这里的close方法,使用TCP提供的具体的实现),向服务端发送FIN(FIN=1)数据包,FIN数据包含有序列值Seq=n。客户端发送FIN数据包后,将自身状态置为FIN_WAIT_1(终止状态1)。

注意:FIN报文的作用是告诉服务端,我将不会主动发起请求。

第二次挥手

图示

第二次挥手

服务端接收到FIN报文,执行passive close(被动关闭) 并将自身状态置为CLOSE_WAIT(半关闭状态)。将序列Seq加1(Ack=n+1),调用read(),向客户端发送ACK返回报文(ACK=1)。

客户端接收到ACK报文,对序列进行校验,无误后,将自身状态置为FIN_WAIT2(终止状态2)。

注意:一旦服务端的TCP发现接收到的报文是FIN报文后,就进入到半关闭状态,将不再接收来自客户端的请求报文。但是服务端依然可以发送请求,客户端也会接收。这个CLOSE_WAIT状态会持续存在一段时间,直到服务端调用close方法。

第三次挥手

图示:

服务端经过一段时间后,会调用close()方法,向客户端发送FIN报文(FIN=1),同样的FIN报文中包含服务端的一个Seq,然后将自身状态置为LAST_ACK(最终应答)。

第四次挥手

图示:

客户端 TCP确认FIN报文后发出应答确认 ACK 报文,并进入了 TIME_WAIT(时间等待)状态。注意此时 TCP 连接还没有释放,必须经过 2∗MSL的时间后,当主动关闭端撤销相应的 TCB 后,才进入 CLOSED 状态。

服务端只要收到了客户端发出的确认,立即进入 CLOSED 状态。同样,撤销 TCB后,就结束了这次的 TCP 连接。可以看到,被动关闭端结束 TCP 连接的时间要比主动关闭端早一些。

关于MSL简单了解下就好: max segement lifetime(最长报文段寿命/最长分节生命期),MSL 是任何 IP数据报能够在因特网中存活的最长时间,任何 TCP 实现都必须为 MSL 选择一个值。RFC1122[Braden 1989]的建议值是 2 分钟,不过源自 Berkelcy 的实现传统上改用 30 秒这个值。这意味着 TIME_WAIT 状态的持续时间在 1 分钟到 4 分钟之间。

总结:TCP断开连接,一共进行四次数据包交互。主动关闭端和被动关闭端都需要向对端发送FIN报文,和接收ACK报文。

提问:为什么TCP断开连接需要四次挥手?

解答:首先我们要知道TCP是一个全双工(客户端和服务端)的连接,只有两端都关闭连接才算真正的关闭。而两边都需要通过FIN报文告诉对方,己方将不会再主动发送请求,等待接收到ACK确认,TCP再进行关闭连接。

加深理解:我们要明确一个思路,当一端先主动发起关闭请求时,只意味着,己方不会再向对方主动发送请求。而对方什么时候不发送主动发送请求,要由对方决定。这就要求对方也需要发送FIN请求。这就要求关闭连接需要四次。

举一个例子:

NO1:

假如你和你女朋友晚上聊天,你想睡觉(或者想玩游戏),然后你会说:“太晚了,我想睡觉。”

NO2:

你老婆正兴奋着聊一个话题,停不下,“我还没说完,你闭嘴,听我说就行了”。

我就想问,你能让她不说,你敢?你能管住自己不说话,但你能管住她?

NO3

一段时间后,你老婆终于说完了,“伦家说累了,要觉觉了。”

NO4

你回复一个ACK:“辛苦”。

此时聊天结束。

提问:为什么需要一个TIME_WAIT状态?

解答:

1.保证可靠的终止连接

我们有没有想过,最后一次挥手如果数据包丢失怎么办?网络上出现丢包是很正常的,如果在最后一次挥手发生丢包现象,那么接收端一直等待,TCP就不会关闭连接。这时候就需要发送端有个TIME_WAIT状态,他会经过一系列处理,发现ACK数据包丢失,然后会再应答一个ACK报文。这样就保证了终止连接的可靠性。

2.保证让迟来的 TCP 报文有足够的时间被识别并丢弃

在 Linux 系统上,一个 TCP 端口不能被同时打开多次,当一个 TCP 连接处于 TIME_WAIT 状态时,我们无法使用该链接的端口来建立一个新连接。反过来思考,如果不存在 TIME_WAIT 状态,则应用程序能过立即建立一个和刚关闭的连接相似的连接(这里的相似,是指他们具有相同的 IP 地址和端口号)。这个新的、和原来相似的连接被称为原来连接的化身。新的化身可能受到属于原来连接携带应用程序数据的 TCP 报文段(迟到的报文段),这显然是不该发生的。这是TIME_WAIT 状态存在的第二个原因。

拓展提问:为什么有时候通过抓包工具查看TCP连接时,发现有时候没有四个数据包?

首先我们知道,我们第一次发起关闭连接请求时,可能正好有个发送请求,此时FIN数据包可能会携带在报文中。所以TCP断开连接就可能只需要三次挥手。

我们知道第三次挥手,需要等待时间,这个等待就是可能被动关闭端仍然有请求发送。那假如没有呢?第二次和第三次就会合并。

总结:实际上我们的TCP连接关闭可能有2次、3次、4次。

关闭一个数据库连接

准备:wireshark(抓包工具),navicat(数据库可视化工具),mysql

说明:mysql的连接是一个TCP连接

1.准备一个已经建立连接的数据库连接

2.用wireshark捕捉一个3306端口

3.准备

这样就可以捕捉3306端口的数据包了

4.关闭数据库连接

7.简单看下

8.我们看后面四个数据包

我们看到,已经抓到了6个数据包,仔细看后面四个数据包是不是对应着FIN、ACK、FIN、ACK四个数据包,和TCP的四次挥手是不是特别相似。

9.第一次挥手

黄色框框是端口为59260向端口为3306端口发送FIN数据包,此时序列值Seq=6。

10.第二次挥手

红色框框是端口3306向端口59260返回ACK数据包,序列值Ack=7。正好是FIN报文Seq的6再加上1,Ack=Seq+1;

11.第三次挥手

此时端口3306向59260发送一个FIN数据包,序列值,Seq=1。

12.第四次挥手

       端口59260向端口3306返回ACK数据包,此时序列值Ack=2,对应着3306端口的序列值Seq为1再加1,Ack=Seq+1

四次握手结束,TCP连接断开。

这篇关于网络协议和Netty(6):大白话说四次挥手和用一个数据库关闭连接的例子进行说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/904591

相关文章

MySQL数据库约束深入详解

《MySQL数据库约束深入详解》:本文主要介绍MySQL数据库约束,在MySQL数据库中,约束是用来限制进入表中的数据类型的一种技术,通过使用约束,可以确保数据的准确性、完整性和可靠性,需要的朋友... 目录一、数据库约束的概念二、约束类型三、NOT NULL 非空约束四、DEFAULT 默认值约束五、UN

MySQL 多表连接操作方法(INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN)

《MySQL多表连接操作方法(INNERJOIN、LEFTJOIN、RIGHTJOIN、FULLOUTERJOIN)》多表连接是一种将两个或多个表中的数据组合在一起的SQL操作,通过连接,... 目录一、 什么是多表连接?二、 mysql 支持的连接类型三、 多表连接的语法四、实战示例 数据准备五、连接的性

MySQL中的分组和多表连接详解

《MySQL中的分组和多表连接详解》:本文主要介绍MySQL中的分组和多表连接的相关操作,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录mysql中的分组和多表连接一、MySQL的分组(group javascriptby )二、多表连接(表连接会产生大量的数据垃圾)MySQL中的

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

利用python实现对excel文件进行加密

《利用python实现对excel文件进行加密》由于文件内容的私密性,需要对Excel文件进行加密,保护文件以免给第三方看到,本文将以Python语言为例,和大家讲讲如何对Excel文件进行加密,感兴... 目录前言方法一:使用pywin32库(仅限Windows)方法二:使用msoffcrypto-too

Pandas使用AdaBoost进行分类的实现

《Pandas使用AdaBoost进行分类的实现》Pandas和AdaBoost分类算法,可以高效地进行数据预处理和分类任务,本文主要介绍了Pandas使用AdaBoost进行分类的实现,具有一定的参... 目录什么是 AdaBoost?使用 AdaBoost 的步骤安装必要的库步骤一:数据准备步骤二:模型

使用Pandas进行均值填充的实现

《使用Pandas进行均值填充的实现》缺失数据(NaN值)是一个常见的问题,我们可以通过多种方法来处理缺失数据,其中一种常用的方法是均值填充,本文主要介绍了使用Pandas进行均值填充的实现,感兴趣的... 目录什么是均值填充?为什么选择均值填充?均值填充的步骤实际代码示例总结在数据分析和处理过程中,缺失数

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

数据库面试必备之MySQL中的乐观锁与悲观锁

《数据库面试必备之MySQL中的乐观锁与悲观锁》:本文主要介绍数据库面试必备之MySQL中乐观锁与悲观锁的相关资料,乐观锁适用于读多写少的场景,通过版本号检查避免冲突,而悲观锁适用于写多读少且对数... 目录一、引言二、乐观锁(一)原理(二)应用场景(三)示例代码三、悲观锁(一)原理(二)应用场景(三)示例

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/