TCP的三次握手和四次挥手

三次握手

既然我们文章要说的是TCP的三次握手,和四次挥手,那么肯定是说的连接,也不是说的不其他的。那么它这个连接的过程说的是什么呢?

在这里插入图片描述

我们还是从图中理解,这样比较好理解,

  • TCP第一次握手:服务端的TCP进程先创建传输控制块TCB,准备接受客户端进程的连接请求,然后服务端进程处于LISTEN状态,等待客户端的连接请求,向服务端发出连接请求报文段,该报文段首部中的SYN=1,ACK=0,同时选择一个初始序号
    seq=i。TCP规定,SYN=1的报文段不能携带数据,但要消耗掉一个序号。这时,TCP客户进程进入SYN—SENT(同步已发送)状态。

简单的来说SYN—SENT状态,同步已发送状态,这是第一次握手的时候的状态。

  • TCP第二次握手:服务端收到客户端发来的请求报文后,如果同意建立连接,则向客户端发送确认。确认报文中的SYN=1,ACK=1,确认号ack=i+1,同时为自己
    选择一个初始序号seq=j。同样该报文段也是SYN=1的报文段,不能携带数据,但同样要消耗掉一个序号。这时,TCP服务端进入SYN—RCVD(同步收到)状态

这个第二次握手就会进入到同步收到状态。

  • TCP第三次握手:客户端进入ESTABLISHED(已建立连接)状态,TCP客户端进程收到服务端进程的确认后,还要向服务端给出确认。确认报文段的ACK=1,确认号ack=j+1,而自己的序号为seq=i+1。
    TCP的标准规定,ACK报文段可以携带数据,但如果不携带数据则不消耗序号,因此,如果不携带数据,则下一个报文段的序号仍为seq=i+1。

而当第三次握手连接完成的时候,已经标志了现在是已经完全的建立了连接,而这个时候就可以进行数据传递了。

有时候就有人会问了,为什么是三次握手而不是两次,也不是四五次呢?一般情况下问这种问题的都会是面试官,如果你在面试过程中已经把这个三次握手说完了之后,他有时候就会问这种问题,让你谈谈你自己的理解,那么为什么呢?

在RFC 793 指出的 TCP 连接使用三次握手的首要原因:he principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.

翻译过来就是三次握手的主要原因是防止旧的重复连接启动引起混淆。

也就是说,如果客户端连续发出多个SYN建立连接的报文的话,在网络拥堵的情况就会出现,一个「旧 SYN 报文」比「最新的 SYN 」 报文早到达了服务端,那么此时服务端就会回一个 SYN + ACK 报文给客户端,客户端收到后可以根据自身的上下文,判断这是一个历史连接(序列号过期或超时),那么客户端就会发送 RST 报文给服务端,表示中止这一次连接。

而如果是两次握手,那么完蛋了,这时候判断不出这个连接是不是历史连接,中断还是不中断,这就没办法处理了,而三次握手就可以在客户端进行第三次发送报文的时候,有足够的上下文来判断这个连接到底是否属于历史连接。

那么为什么不是四次连接呢?大家可以继续翻到上面的图,如果是四次连接,那么也就是说,把ACK和SYN进行了分开,seq=y和ack=x+1这两步进行了分开,虽然四次握手也能够完成这一步,但是为了省事,人家还是三部就做完了,这样一来,也能确保双方的初始序列号能被可靠的同步,何必在多费一步操作呢?

四次挥手

既然我们TCP连接的时候进行了三次握手,为什么要中断的时候,我们要进行四次挥手呢?这还是得从图中来理解这个事情。

在这里插入图片描述

  • 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送
  • 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。
  • 服务器B关闭与客户端A的连接,发送一个FIN给客户端A
  • 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1

那么为什么是四次呢?之前阿粉面试别人的时候,有个哥们给我了一句话,由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这话比较笼统,但是没解释清楚为啥要做四次挥手,这是最尴尬的,然后问详细的样子是什么样的,他也解答的不错。

那么为什么呢?

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

也就是说,在关闭的时候,为了确认是否关闭连接,ACK的报文和FIN的报文是进行分开发送,而这时候,挥手的次数也就从三次变成了4次,这样是不是就好理解一点了。

参考链接:https://blog.csdn.net/yinlidong77/article/details/121013566

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/16993.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

gradle Task 详解

目录 Task定义和配置 Task的执行阶段 Task 的依赖 Task 指定执行顺序 Task 主gradle引入其他的gradle文件 将某一个task挂载到指定的task之后执行 gradle task官网:Task - Gradle DSL Task定义和配置 查看工程下所有的task,使用如下命令 gradle …

【Linux】浅谈eloop机制

目录 1.eloop 机制 2.eloop结构体 2.1.eloop_data结构体 2.2 Socket事件结构体 2.3 Timeout事件结构体 2.4 Signal事件结构体 3.eloop_init 4.eloop_run 4.1 signal事件 4.2 socket事件 4.3 timeout事件 1.eloop 机制 主线程中启动事件监听机制,对不同的…

深度学习模型压缩与优化加速

1. 简介 深度学习(Deep Learning)因其计算复杂度或参数冗余,在一些场景和设备上限制了相应的模型部署,需要借助模型压缩、系统优化加速、异构计算等方法突破瓶颈,即分别在算法模型、计算图或算子优化以及硬件加速等层…

如何优雅地停掉线程?

很久很久以前,在一个名为“Springboot”的村庄中,住着一群热爱编程的程序员。他们喜欢探索新技术、优化自己的代码,为了打造更好的软件而不断努力着。 在这个村庄中,有一个名叫小明的程序员,他是村庄中最优秀的程序员…

一文打通java中内存泄露

目录 前置知识 内存泄漏(memory leak) 内存溢出(out of memory) Java中内存泄露的8种情况 静态集合类 单例模式 内部类持有外部类 各种连接,如数据库连接、网络连接和IO连接等 变量不合理的作用域 改变哈希值 …

第二十八章 React脚手架配置代理

为了更好地理解如何在React应用程序中配置代理,我们需要先了解什么是代理。 代理是一种充当客户端和服务器之间中间人的服务器。当客户端向服务器发送请求时,代理服务器将接收请求并将其转发到服务器。服务器将响应发送回代理服务器,代理服务…

机器视觉工程师职场四点“心态>交流=思路>知行合一”

视觉人机器视觉团队,他们热爱机器视觉行业,爱学习,爱分享。这一路上,首先感谢粉丝们805天一如既往的支持。我想团队拥有这些粉丝,是富有的,也是我们一直创作的动力。 是否记得毕业季,自己的豪言壮语。希望你毕业三年后,无论结果如何,不忘初心,继续前行。 机器视觉工程…

Flutter 中使用 Widgetbook 管理你的组件

Flutter 中使用 Widgetbook 管理你的组件 前言 Flutter 界面开发中我们有几个痛点 : 与设计师协作复用一套设计规范(figma) 可视化的管理你的组件代码(基础组件、业务组件) 不同设备尺寸测试你的组件 实时修改你的测试…

python并发编程:什么是并发编程?python对并发编程有哪些支持?

Python并发编程是指同时执行多个任务的编程模式。Python提供了多种实现并发编程的方式,包括多线程、多进程、协程、异步IO等。 为什么要引入并发编程 假设以下两个场景: 场景一: 一个网络爬虫,按顺序爬取花了一个小时,采用并发…

spring-模型数据和视图---视图解析器的说明以及大量代码演示

目录 spring-模型数据 ● 说明 应用实例需求 创建后面所有代码执行成功之后跳转的vote_ok.jsp页面 方式 1: 通过 HttpServletRequest放入 request 域 创建 Master类 创建Pet类 创建model_data.jsp 修改 VoteHandler增加方法 创建vote_ok.jsp, 显示数据 完成测试(Post…

[LeetCode周赛复盘] 第 103 场双周赛20230429

[LeetCode周赛复盘] 第 103 场双周赛20230429 一、本周周赛总结2656. K 个元素的最大和1. 题目描述2. 思路分析3. 代码实现 2657. 找到两个数组的前缀公共数组1. 题目描述2. 思路分析3. 代码实现 2658. 网格图中鱼的最大数目1. 题目描述2. 思路分析3. 代码实现 2659. 将数组清…

Docker consul

目录 一、Docker consul的容器服务和发现 ①服务注册与发现的含义 ②什么是consul 二、服务部署 ①部署consul服务 (1)查看集群信息 (2)通过http api获取集群信息 ②部署registrator服务器 (1)安装…

计算机视觉毕业后找不到工作怎么办?怒刷leetcode,还是另寻他路?

文章目录 一、计算机视觉毕业后找不到工作怎么办?二、大环境:前两年的泡沫太大三、还是要把自己的基本功搞扎实,真正的人才什么时候都紧缺四、转换思路,另投他坑五、要有毅力,心态放平六、最后的建议 一、计算机视觉毕…

应急加固初试(windows sever 2008)

前言 红中(hong_zh0) CSDN内容合伙人、2023年新星计划web安全方向导师、 华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、 吉林师范大学网安大一的一名普通学生、搞网安论文拿了回大挑校二、 阿里云专家博主、华为网络安全云享专家、腾讯云自媒体分享计划博主 …

【服务器】威联通NAS文件共享 - 搭建SFTP服务并内网穿透实现在外远程访问

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员,2024届电子信息研究生 目录 前言 1. 威联通NAS启用SFTP 2. 测试局域网访问 3. 内网穿透 3.1 威联通安装cpolar内网穿透 3.2 创建隧道 3.3 测试公网远程访问 4. 配置固定公网TCP端口地址 4.1 保留一个固定TCP…

chatGPT+Midjourney制作绘画本

chatGPTMidjourney制作绘画本 灵感来源:https://www.bilibili.com/video/BV1N24y1F7ga/?spm_id_from888.80997.embed_other.whitelist&vd_source6dd97671c42eb7cf111063714216bd0b 最终效果: 绘本故事 故事塑造能力弱的人可以使用chatGPT来帮助编…

JAVAWeb11-服务器渲染技术 -JSP-01-JSP基础

1. 现状 1、JSP 使用情况 2、Thymeleaf 使用情况, 通常和 SpringBoot 结合(也会讲) 3、Vue 使用情况 2. 学 JSP 前,老师要说的几句话 目前主流的技术是 前后端分离 (比如: Spring Boot Vue/React), 我们会讲的.[看一下]JSP 技术使用在逐渐减少&#xff…

C. Maximum Subrectangle(思维 + 考察两个数组相乘得到的矩阵的含义)

Problem - C - Codeforces 给定两个正整数数组 a 和 b,长度分别为 n 和 m。 定义矩阵 c 为一个 nm 的矩阵,其中 ci,jai⋅bj。 你需要在矩阵 c 中找到一个子矩形,使得它的元素之和最多为 x,并且它的面积(即元素总数&a…

【Redis】Redis分布式锁的10个坑

文章目录 前言1. 非原子操作(setnx expire)2.被别的客户端请求覆盖( setnx value为过期时间)3. 忘记设置过期时间4. 业务处理完,忘记释放锁5. B的锁被A给释放了6. 释放锁时,不是原子性7. 锁过期释放&…

【Linux内核解析-linux-5.14.10-内核源码注释】MM内存管理内核启动初始化源码解析

源码 这是Linux内核中的mm_init函数的代码,其作用是初始化内存管理相关的组件和数据结构。 static: 这是一个函数声明修饰符,表示该函数只在当前文件中可见。 void __init: 这是函数的返回类型和修饰符,表示该函数是内核初始化代码。 page…