TCP 为什么三次握手而不是两次握手(正解版)

2023-11-07

参考文章

Why do we need a 3-way handshake? Why not just 2-way

大部分网络博客的错误解读

首先需要声明的是, 百度搜索到的大部分网络博客关于这个问题的解答都是不清晰或者不准确的。 讨论这个问题的大部分博客都会引用《计算机网络》的内容:

  1. 防止已失效的连接请求又传送到服务器端,因而产生错误

不幸的是, 这种解释是不准确的, TCP 采用三次握手的原因其实非常简单, 远没有大部分博客所描述的那样云山雾绕。

这里先给出结论:

  • 为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤
  • 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认

先修知识

TCP 通信流程

TCP 的通信流程
在这里插入图片描述

上图中的每一个箭头都代表着一次 TCP数据包的发送

  • 需要注意的是, 上图中出现的 ACK = x +1 的写法很容易让人误以为数据包中的 ACK 域的数据值被填成了 y+1 。 ACK = x+1 的实际含义是:
    • TCP 包的 ACK 标志位(1 bit) 被置成了 1
    • TCP 包的确认号(acknowledgement number ) 的值为 x+1
  • 类似的, TCP 数据包中的 SYN 标志位, 也容易与序号(sequence number) 混淆, 这点需要读者注意

TCP 数据包结构图
TCP包结构图

为什么 TCP 需要握手这个操作

在解答为什么 TCP 需要三次握手, 而不是两次之前, 首先需要回答的问题是:

  • 为什么需要握手这个操作, 能不能不握手?

如果读者对比一下 UDP 的通信流程和 TCP 的通信流程, 可以发现, 在 UDP 协议中, 是没有握手这个操作的。
在这里插入图片描述

这里就引出了 TCP 与 UDP 的一个基本区别, TCP 是可靠通信协议, 而 UDP 是不可靠通信协议。

  • TCP 的可靠性含义: 接收方收到的数据是完整, 有序, 无差错的。
  • UDP 不可靠性含义: 接收方接收到的数据可能存在部分丢失, 顺序也不一定能保证。

UDP 和 TCP 协议都是基于同样的互联网基础设施, 且都基于 IP 协议实现, 互联网基础设施中对于数据包的发送过程是会发生丢包现象的, 为什么 TCP 就可以实现可靠传输, 而 UDP 不行?

TCP 协议为了实现可靠传输, 通信双方需要判断自己已经发送的数据包是否都被接收方收到, 如果没收到, 就需要重发。 为了实现这个需求, 很自然地就会引出序号(sequence number)确认号(acknowledgement number) 的使用。

发送方在发送数据包(假设大小为 10 byte)时, 同时送上一个序号( 假设为 500),那么接收方收到这个数据包以后, 就可以回复一个确认号(510 = 500 + 10) 告诉发送方 “我已经收到了你的数据包, 你可以发送下一个数据包, 序号从 510 开始” 。

这样发送方就可以知道哪些数据被接收到,哪些数据没被接收到, 需要重发。

为什么需要三次握手,而非两次

正如上文所描述的,为了实现可靠传输,发送方和接收方始终需要同步( SYNchronize )序号。 需要注意的是, 序号并不是从 0 开始的, 而是由发送方随机选择的初始序列号 ( Initial Sequence Number, ISN )开始 。 由于 TCP 是一个双向通信协议, 通信双方都有能力发送信息, 并接收响应。 因此, 通信双方都需要随机产生一个初始的序列号, 并且把这个起始值告诉对方。

于是, 这个过程就变成了下面这样。
在这里插入图片描述

下面这个流程图描述的和上面一样, 但是更加清楚的展示了 TCP 数据包标志位, 以及数据域的命名来源。

Alice Bob SYN =1 , seq = x SYNchronize with my Initial Sequence Number of x SYN =1, ACK = 1, seq = y , ack = x+1 I received your ISN, I ACKnowledge that I am ready for [x+1] SYNchronize with my Initial Sequence Number of y ACK =1 , seq = x+1, ack = y+1 I received your syn, I ACKnowledge that I am ready for [y+1] Alice Bob

题外话

有一位读者关注到了三次握手中, 序列号变化的问题, 让笔者临时想起了曾经困扰自己的一个问题

  • 为什么三次握手最后一次握手中, 在上面的示意图中回复的 seq = x+1 。

答案: (此处感谢 “楚天千里清秋” 的提醒, 进行了修正)

acknowledgement number 的作用是向对方表示,我期待收到的下一个序号。 如果你向对方回复了 ack = 31, 代表着你已经收到了序号截止到30的数据,期待的下一个数据起点是 31 。

TCP 协议规定SYN报文虽然不携带数据, 但是也要消耗1个序列号, 所以前两次握手客户端和服务端都需要向对方回复 x+1 或 y+1 。

在这里插入图片描述
在这里插入图片描述
值得注意的是, 如上图所说, 最后一次握手在默认不携带数据的情况下, 由于SYN 不是 1 , 是不消耗序列号的。 所以三次握手结束后, 客户端下一个发送的报文中 seq 依旧是 x+1, 示意图如下

在这里插入图片描述
注意到, 上图第四步发送的 seq 和第三次握手的 seq 是一样的, 体现了最后一次握手, 默认不消耗序列号的特点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP 为什么三次握手而不是两次握手(正解版) 的相关文章

  • Linux 环境基础开发工具的使用

    目录 一 软件包管理器 yum 1 什么是软件包 2 查看软件包 3 如何安装软件 4 如何卸载软件 二 Linux开发工具 1 Linux编辑器 vim使用 1 1 vim的基本概念 1 2 vim的基本操作 1 3 vim正常模式命令集
  • springboot项目部署宝塔提示成功,实际没有启动

    被这个问题搞得头大了 默认项目用户为www 把项目用户改成root即可启动成功 启动成功后 再刷新还是显示成功运行
  • web测试的基本测试点

    一 什么是Web测试 如果要了解web测试 首先我们的清楚web项目是什么 一般指本b s架构项目也就是通过浏览器进行访问的 在日常生活工作中 基于web系统的应用非常多 打开电脑 抢火车票我们会登陆12306网站 添置衣物我们会登陆天猫
  • Codeforces 996 A Hit the Lottery

    A Hit the Lottery time limit per test 1 second memory limit per test 256 megabytes input standard input output standard
  • 副业搞钱的几个野路子:两个年入10万的零成本赚钱项目

    不想担太多风险 想低成本歪主意 最佳的选择不外乎就是做服务和卖交互式产品 搞交互式项目 最大的成本是时间成本 很多人都不缺时间 缺的是歪主意思维和变通能力 独豆豆不如众豆豆 这几天辨认出了三个歪主意的野路子 写个文章给大家互动互动 这三个主
  • Fisco Bcos区块链二(搭建使用控制台,体验Holleworld合约调用)

    文章目录 区块链开荒 技术文档 https fisco bcos documentation readthedocs io zh CN latest index html 2 配置及使用控制台 1 准备依赖 2 启动并使用控制台 3 部署及
  • 100天精通Python(可视化篇)——第97天:Pyecharts绘制多种炫酷热力图参数说明+代码实战

    文章目录 专栏导读 1 热力图介绍 2 基础热力图 3 添加色块数值 4 添加热力标尺 5 修改色块颜色 6 不同区间颜色 7 炫酷模块1 8 炫酷模块2 书籍推荐 专栏导读 本文已收录于 100天精通Python从入门到就业 本专栏专门针
  • 【构建ML驱动的应用程序】第 8 章 :部署模型时的注意事项

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • 最大堆和最小堆

    堆和栈的区别 一 堆栈空间分配区别 1 栈 操作系统 由操作系统自动分配释放 存放函数的参数值 局部变量的值等 其操作方式类似于数据结构中的栈 2 堆 操作系统 一般由程序员分配释放 若程序员不释放 程序结束时可能由OS回收 分配方式倒是类
  • 【从零开始】力扣刷题(2)

    前言 我根据这里的表单开始刷力扣 数组的改变移动 453 最小操作次数使元素相等 写了一个但超过时间限制 碰到 1 100000000 就超出时间限制了 就不错误示范了 看了一个评论 拍案叫绝 665 非递减数列 想了一天 看了很多解答 好
  • 【数据结构2】算法的基本概念

    算法的基本概念 程序 数据结构 算法 数据结构 如何把现实世界的问题信息化 将信息存进计算机 同时还要实现对数据结构的基本操作 算法 如何处理这些信息 以解决实际问题 算法的特性 有穷性 一个算法必须总在执行有穷步之后结束 且每一步都可在有
  • Windows 快速配置ip地址

    说明 生活中 很多时候我们要背着电脑往返于某些固定的地方 家里 公司 实验室 寝室等等 每次开电脑后第一件事情就是用图形界面点点点点再点改IP地址 这样非常的麻烦 如何快速配置为自己量身定做的IP地址呢 当然是用脚本 bat 脚本 将下面脚
  • Stata数据处理

    作者 Economicoder 公众号 数据学徒 1 快捷键 Fn F2 描述数据 describe Fn PgUp 搜索先前命令 Ctrl 8 打开 data editor browse Ctrl 9 新建do文档 Ctrl D 执行在d
  • 图片转换js (img对象,file对象,base64,canvas对象),以及图片压缩方式

    首先想一想我们有哪些需求 大多时候我们需要将一个File对象压缩之后再变为File对象传入到远程图片服务器 有时候我们也需要将一个base64字符串压缩之后再变为base64字符串传入到远程数据库 有时候后它还有可能是一块canvas画布
  • 【blog】使用github-pages搭建个人博客

    我的博客 以此博客记录学习过程及相关学习笔记 一 选择模板 1 在Jekyll Themes 或者jekyll sites 选择一个你喜欢的模板直接下载 2 在github新建一个项目 选择一个主题 外链图片转存失败 源站可能有防盗链机制
  • 数据库的模糊查询

    命中率越高 策略越好 数据库的模糊查询 work918 在SQL中 模糊查询可以使用LIKE关键字来实现 LIKE关键字后面可以跟一个模式 其中 表示任意数量的字符 表示一个字符 例如 如果你想在一个名为students的表中查找所有名字以
  • python计算正方形、立方体、圆、球的面积和体积

    usr bin env python encoding UTF 8 import math 正方形的面积 def square mianji x return x x 立方体的表面积 def cube x return xx6 立方体的体积
  • linux系统下部署02-InfluxDB的安装和设置密码

    InfluxDB是一个当下比较流行的时序数据库 InfluxDB使用 Go 语言编写 无需外部依赖 安装配置非常方便 适合构建大型分布式系统的监控系统 一 InfluxDB 简介 InfluxDB 是用Go语言编写的一个开源分布式时序 事件
  • 使用高效代理抓取58同城巴州二手房信息并保存至excel

    声明 此程序旨在技术学习交流 促进网络安全 不作任何商业用途 违者责任自负 此程序就是使用代理IP来反爬的一个小案例 使用的高效代理 通过API每次请求提取一个代理IP 一个代理IP 必须是高匿代理 隐藏真实IP 相当于一台主机 只要主机足

随机推荐

  • 无需解密代码!软件保护专家VMProtect 2020全新升级!更丰富的保护功能

    VMProtect是新一代的软件保护实用程序 具有内置的反汇编程序 可与Windows和Mac OS X可执行程序配合使用 还可以链接编译器创建的MAP文件 以快速选择代码片段进行保护 VMProtect的基本原则是通过使应用程序代码和逻辑
  • ReactNative——导航器react-navigation(堆栈式导航器篇)

    react navigation 安装核心包 yarn add react navigation native 安装 react navigation native本身依赖的相关包 react native reanimated 动画库 r
  • MVC中前台Model转Json传到后台

    C 代码 string str Newtonsoft Json JsonConvert SerializeObject Model JS代码 var theString str theString theString replace quo
  • C语言实验——求两个整数之和

    C语言实验 求两个整数之和 C语言实验 求两个整数之和 求两个整数之和 不从键盘输入数据 直接使用赋值语句 a 123 b 456 输入数据 然后计算两个整数之和输出 Input 无输入数据 Output 输出a和b之和 Sample Ou
  • 5.Java中的基本数据类型有哪些?

    Java中的基本数据类型有哪些 Java是一个强类型语言 Java中的数据必须明确数据类型 在Java中的数据类型包括基本数据类型和引用数据类型两种 Java中的基本数据类型 数据类型 关键字 内存占用 成员变量初始值 取值范围 整数类型
  • Coursera

    该系列仅在原课程基础上部分知识点添加个人学习笔记 或相关推导补充等 如有错误 还请批评指教 在学习了 Andrew Ng 课程的基础上 为了更方便的查阅复习 将其整理成文字 因本人一直在学习英语 所以该系列以英文为主 同时也建议读者以英文为
  • Qt 判断QString是否为空

    isEmpty QString isEmpty returns true QString isEmpty returns true QString x isEmpty returns false QString abc isEmpty re
  • Linux 存储结构

    软硬链接 windows中的快捷方式 ln 参数 目标 参数 使用 s s表示创建软链接 默认创建的是硬链接 f 强制创建文件或目录的链接 i 覆盖先询问 v 显示创建过程 echo hello wolrd gt readme txt 创建
  • 相关性分析的五种方法

    相关分析 Analysis of Correlation 是网站分析中经常使用的分析方法之一 通过对不同特征或数据间的关系进行分析 发现业务运营中的关键影响及驱动因素 并对业务的发展进行预测 本篇文章将介绍5种常用的分析方法 在开始介绍相关
  • 【H.264/AVC视频编解码技术详解】十二、解析H.264码流的宏块结构(下):H.264帧内编码宏块的预测结构

    H 264 AVC视频编解码技术详解 视频教程已经在 CSDN学院 上线 视频中详述了H 264的背景 标准协议和实现 并通过一个实战工程的形式对H 264的标准进行解析和实现 欢迎观看 纸上得来终觉浅 绝知此事要躬行 只有自己按照标准文档
  • Docker部署nacos单机版

    Docker部署nacos单机版 1 拉取镜像 获取最新nacos docker pull nacos nacos server 获取指定版本的nacos docker pulll nacos nacos server 1 3 0 2 导入
  • 软件工程概述思维导图总结(二)

    软件工程之软件过程 关于作者 作者介绍 博客主页 作者主页 简介 JAVA领域优质创作者 一名在校大三学生 在校期间参加各种省赛 国赛 斩获一系列荣誉 关注我 关注我学习资料 文档下载统统都有 每日定时更新文章 励志做一名JAVA资深程序猿
  • 使用Python分析股价波动周期

    基本思路是获取股价收盘信息后 使用希尔伯特黄变换将股价波动数据拆解为不同周期的波动曲线 再本别利用频谱分析计算每一个曲线的频率 目标是将股价波动数据拆解为不同周期波动的叠加态 1 获取收盘价 富途有很好的API接口 给我这种小散送了每个月的
  • 协程是安全的吗?

    前言 我们都知道 多个线程操作同一个变量 是有线程安全问题的 但是 如果换成是 多个协程操作同一个变量 呢 还会有安全问题吗 实验环境 Windows 11 Go 1 20 2 过程 先看一段Golang代码示例 func main cou
  • 【DVWA】DVWA的下载、安装与配置

    DVWA DVWA的下载 安装与配置 简介 DVWA是一个基于php的网络安全练习的环境 也就是可以用来练习hacker技术的地方 无须自己找个网络下手或者搭建安全环境来练习网络攻防了 DVWA也是一个对网上常见的漏洞的入门的平台 有sql
  • 高通recovery流程分析(编译、界面、图片)

    目录 recovery 界面菜单 recovery 界面操作 recovery 启动流程 recovery 编译makefile recovery 图片大小 ramdisk boot img recovery img之间的关系 author
  • Linux find命令查找文件

    如果要去 目录下找一个名为test txt的文件 find name test txt 如果要去 目录下找出所有后缀为txt的文件 find name txt 删除所有查找到的文件和文件夹 慎用 rm rf find name txt
  • openwrt系统初始化分析

    openwrt固件启动后 进入uboot 加载内核 启动init进程 而init进程包含在procd进程中 启动代码如下 int main int argc char argv pid t pid sigaction SIGTERM sa
  • [DBNETLIB][ConnectionOpen(Connect()).]SQL Server 不存在或拒绝访问 数据库错误 解决办法总结

    原因 1 查看是不是没有在数据库中添加数据库服务器地址 2 查看端口是否打开 MSSQL默认是TCP 1433 3 SQL服务项中服务是否开启或启动 4 防火墙是否将TCP 1433端口 添加例外 5 是否开启了VIA服务 6 最好关闭数据
  • TCP 为什么三次握手而不是两次握手(正解版)

    参考文章 Why do we need a 3 way handshake Why not just 2 way 大部分网络博客的错误解读 首先需要声明的是 百度搜索到的大部分网络博客关于这个问题的解答都是不清晰或者不准确的 讨论这个问题的