计算机网络——TCP三次握手详解为什么两次不行

2023-11-02

TCP是面向连接的(connection-oriented),即收发双方在发送数据之前,必须首先建立一个连接,这样在连接断开之前,就一直使用这个连接传输数据。建立连接包括参数的设置、内存空间的分配,收发双方参数的协商等,这一过程需要经过三次成功的沟通,一般叫做“三次握手” (a three-way handshake)。

用通俗的话来讲,这三次沟通就是:

  • 发起方:“你好,请问我可以跟你建立一个连接吗?”(发送请求,等待回复)
  • 接收方:“好啊,我准备好了,来吧。”
  • 发起方:“好的,谢谢,我现在开始向你发送数据了。”

当然,在具体的实现过程中,还包含许多细节,以下一一阐述。

1. TCP报文段结构

要了解三次握手的过程中发送了什么报文,首先得知道TCP报文段由哪些字段构成,其中哪些字段在这个过程中起了关键作用。
在这里插入图片描述
我们重点关注以下几个字段:

  • Sequence number:序列号,用来标记一个报文段的序号,报文段首字节的字节流编号
  • Acknowledgment number:确认号,只有ACK标志位为1时,确认序号字段才有效
  • ACK:用于指示确认号是有效的
  • SYN:同步序列编号(Synchronize Sequence Numbers)

2. 三次握手

接下来更为仔细地观察一条TCP连接是如何建立的。
假设运行在一台主机(客户)上的进程想与另一台主机(服务器)上的进程建立一条连接。客户中的TCP会以如下的方式与服务器中的TCP建立一条TCP连接:
在这里插入图片描述

  • 第一步:客户端的TCP向服务器端的TCP发送一个特殊的TCP报文段,这个报文段不包含应用层数据,且其首部的SYN被置为1,这个特殊的报文段称为SYN报文段。并且,客户机随机选择一个初始序号(client_isn, initial sequence number),并将该值放在序列号字段下。客户端发送SYN报文段,并进入SYN_SENT状态,等待服务器确认。
  • 第二步:一旦服务端收到该TCP SYN报文段(从SYN标记位为1可以判断),会为该连接分配TCP缓存(buffers)和变量,并发送一个允许连接的报文段 (connection-granted segment)给客户TCP。这个报文段也不包含应用层数据,并且SYN同样被置为1,此外ACK标记位也为1,确认号为client_isn+1,并且选择一个初始序号server_isn作为序列号字段的值。这个报文段被称为SYNACK报文段。此时服务器进入SYN_RECV状态。
  • 第三步:客户端收到SYNACK报文段(通过其中的SYN,ACK,确认号可以判断)之后,也为该连接分配缓存和变量。然后客户机会再次向服务端发送一个确认报文,ACK标记位为1,确认号为server_isn+1,(这次SYN为0,SYN只在前两次握手中置为1),这次的报文段可以携带来自应用层的数据。此时客户端进入ESTABLISHED状态。服务端收到这个报文段后,也进入ESTABLISHED状态,此时连接就算完全建立好了,双方可以相互发送数据。

3. SYN洪泛攻击

在上面的讨论中我们知道,服务器收到一个SYN报文段时,分配并初始化连接变量和缓存,然后发送一个SYNACK进行响应。在收到来自客户端的ACK报文段之前,连接并没有完全建立,我们称它为半开连接 (half-open connection)。如果客户不发送ACK以完成三次握手的第三步,那么服务器会在一定时间内终止该半开连接,并回收分配的资源。

在这样的协议下,很容易被一种叫做SYN洪泛攻击 (SYN flood attack) 的拒绝服务攻击 (Denial of Service (DoS) attack) 侵袭。攻击者向服务器发送大量的TCP SYN报文段,而不完成三次握手的第三步,这样服务器不断为这些半开连接分配资源,导致服务器的连接资源消耗殆尽。

目前有一种防御机制可以抵御这种攻击,称为SYN cookie

这种机制的思想在于,在收到SYN之后不马上进行分配资源(因为怕了),而是在第三步时判断连接的发起者是否为一个合法用户,如果是,再分配资源并建立连接。

首先,当服务器收到一个SYN时,不马上分配资源,而是按如下方式生成一个初始的序列号:该序列号是 “SYN报文段中的源和目的IP地址与端口号以及一个只有服务器自己知道的秘密数 (secret number) ” 的hash值,也就是说,只有知道这个秘密数,才可能算出这个序列号(这个初始序列号就称为“cookie”)。然后服务器就发送包含这个初始序列号的SYNACK。需要注意的是,服务器此时不维护任何关于该SYN的状态信息,甚至不用记住这个cookie值。所以如果客户没有返回一个ACK,那么对服务器来说就当什么时都没发生,现在SYN洪泛攻击就做不成了。

那么合法用户是怎样完成第三个步骤的呢?其实并没有什么改变,任然按照原来的方式进行,发送一个ACK给服务器。此时需要动点手脚的是服务端,服务端怎么判断这个ACK报文是对之前的SYNACK的确认呢?很简单,因为之前的SYNACK的序列号是根据“SYN报文段中的源和目的IP地址与端口号以及一个只有服务器自己知道的秘密数”算出来的,那么这次如果还是那个用户的话,那么源和目的IP地址与端口号是不会变的,然后秘密数服务端也知道,用原来的hash函数一算,就得出来了该序列号,然后加1,看是不是跟这个ACK报文的确认号相等,如果相等,那说明这个ACK对应之前的SYNACK,是合法的,于是创建一个连接。

4. 为什么是“三次”

首先,为什么是三次握手而不是四次或者更多?这个问题是比较简单的,因为既然三次能够解决的问题,为什么非要用四次来浪费资源?

但其实问题的重点在于,为什么不能只用两次?第三次握手去掉不行吗?
对于应对SYN洪泛攻击的改进版的“三次握手”来说(见上文),第三次握手肯定是必须的,这个显而易见。

那如果不考虑攻击呢?两次握手就能搞定吗?

谢希仁版《计算机网络》对这个问题进行了讨论。总的来说,三次握手是为了防止当已失效的连接请求报文段突然又传到服务端,造成双方的不一致,导致资源的浪费。

“已失效的连接请求报文段”指的是这样的情况,客户端发出一个SYN报文段,由于阻塞或者其他原因在网络中滞留,以至于客户端认为丢包了(其实并没有丢),于是重新发出一个SYN报文段,假设这一次顺利完成了,那么双方建立连接。这看起来似乎没什么问题,但网络中有一个隐患,就是那个还在网络中传输的SYN报文段,如果这个SYN在连接期间被服务端收到了,那服务端只会无视它,这样就万事大吉了,但如果是在连接释放之后被收到呢?此时服务端认为有人向他发出连接请求,于是响应一个SYNACK回去,如果采用两次握手的话,那么服务器认为此时连接已经建立好了。但是当客户端收到这个SYNACK时,如果他并没有发起连接,那么他不会理睬这个SYNACK,就当没事发生过(如果客户端此时正好发起连接,那其实他也不会理睬这个SYNACK,因为确认号不对啊。)。那问题就大了,这时候服务器以为连接好了,向客户端发送数据,而客户端处于CLOSED状态,会丢弃这些包,这样就很浪费了。并且还有一个尴尬的问题,就是这个时候当客户端打算发起连接时,服务端又不理睬了,在这里尬这,他们就别想互发数据了。当然这些问题似乎不是不可解决的,当客户端发现服务端老是向自己发数据,而自己总是丢弃,可能会向服务端发一个RST(报文段的RST标记号为1),强制服务端关闭连接。但资源总归是浪费了一会了。而用三次握手就不会出现这样的问题。


相关阅读:
计算机网络——TCP四次挥手过程详解
TCP连接的三次握手四次挥手——类比异地恋情侣开始交往和分手(通俗易懂)

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

计算机网络——TCP三次握手详解为什么两次不行 的相关文章

随机推荐

  • 解决STM32驱动0.96OLED不亮的问题

    问题描述 使用STM32无法驱动OLED 解决方案 1 检查硬件连接是否有误 OLED STM32 VCC 5V或3 3V SDA SDA SCL SCL GND GND 备注 最好接STM32最小系统版的3 3V 当连接STM32最小系统
  • Javaio流

    io流 关于Java的io流一般按照数据操作类型可以分为字节流与字符流 首先来说一下字节流 字节流 字节流的方法都是以stream结尾的 字节流的用途 转换图片为二进制 转换音频 视屏为二进制 字符串等也可以转为二进制 字节流常用于图片 音
  • 签到题【牛客算法周周练6E】【暴力枚举+线段树】

    题目链接 题目保证数据随机 数据随机真的是太强了 直接可以跑最坏时候是的复杂度 直接暴力建线段树 然后更新的时候更新到底 查询的时候也是查询到底 因为数据随机 所以其实被处理的次数是很少的 因为要刚好是set里有的 或者是set里没有的 这
  • Unity3D-----三维数学(向量)

    Unity3d gt 三维数学之向量 一 向量 1 什么是向量 2 向量的形式 3 向量的大小 4 向量的方向 二 向量运算 1 向量相减 2 向量相加 3 向量与标量的乘除法 4 点乘 5 叉乘 三 三角函数 1 角的度量单位 2 三角函
  • Labelme 目标检测和语义分割的数据标注

    1 安装labelme 打开conda prompt 输入以下代码创建虚拟环境 打开虚拟环境 安装lelme conda create n labelme python 3 6 创建虚拟环境 conda activate labelme 打
  • 解决idea出现报错:Error running,Command line is too long. Shorten command line

    报错的原因 因为项目需要打印的环境变量太长 超过了限制 需要缩短命令行来解决问题 解决办法 方法一 Edit Configurations 将默认的Shorten command line的值user local default 改为 JA
  • 格式工厂多个图片合并成一个PDF的报错

    使用图片合并PDF功能时 当图片数量超过50会报错 找到imgconv py文件 将50改为500 保存 现在可以支持100张图合并成一个PDF文件了 但是超过150张程序会直接闪退 正在解决中 补充说明 1 如何设置PDF压缩比 打开 g
  • 有奖调研

    简介 感谢您一直以来对阿里云通信短信服务的支持 为了提升用户体验 为您在数字化转型的通信之路提供助力 云通信短信服务将发起一次满意度调研 有关短信服务 无论使用情况 抑或功能需求 还是文档 产品介绍页 计算与账单 控制台 API SDK 售
  • TypeError Cannot read properties of undefined (reading ‘matched‘)vue项目创建之后写路由报错

    vue项目创建之后写路由报错 原代码 修改之后代码 在 import 路由文件后 命名为Router 就会出现报错 原因 router 才是Vue实例化的配置字段名称 不识别其他的
  • Linux下访问数据库

    Linux下访问数据库 声明 本文只简单描述Linux系统下访问mysql数据库的步骤 关于连接上数据库之后的简单的对于数据库的增删改查等操作只是稍微提及 关于增删改查的语句书写 本文不再讲述 一般来说 访问数据库有如下几个步骤 1 初始化
  • C#控制台程序中使用log4.net来输出日志

    Apache log4net 库是一个帮助程序员将日志语句输出到各种输出目标的工具 log4net 是优秀的 Apache log4j 框架到 Microsoft NE T 运行时的端口 我喜欢他可以自定义输出 区分等级等特点 导入库 我们
  • Android自定义控件(三)---实战篇(详解onMeasure)

    接着Android自定义控件 二 实战篇的讲解 这篇我们来详细讲一下测量 onMeasure 和绘制 onDraw 这两个方法 首先 我们来看测量 onMeasure 方法 在这个方法里 我们主要是设置控件的宽高 widthMeasureS
  • jqgrid 翻页记录选中行

    简单的jqgrid列表 list jqGrid url contextPath getList postData data datatype json colNames 用户名 密码 colModel name name index nam
  • 递归算法

    一 一半又一只 一个人赶着鸭子去每个村庄卖 每经过一个村子卖去所赶鸭子的一半又一只 这样他经过了七个村子后还剩两只鸭子 问他出发时共赶多少只鸭子 经过每个村子卖出多少只鸭子 1 题目分析 设经过第n个村子时有fun n 只鸭子 卖去fun
  • java 根据数据库表生成实体类工具

    public class CodeGenerator 修改生成配置 public static String dbUrl 数据库连接串 public static String dbName 账号 public static String
  • 【js】Object.entries的用法

    Object entries是返回一个键值对数组 const obj one 1 two 2 three 3 const result Object entries obj console log result one 1 two 2 th
  • 【Go】Go 的项目目录

    文章目录 一 Go 的项目目录 1 适合个人开发者 2 目前流行的项目结构 3 适合企业开发者 二 Go 项目构建及编译 第一个 Go 程序 参考链接 一 Go 的项目目录 进行Go语言开发的时候 我们的代码总是会保存在 GOPATH sr
  • 阿里云物联网——MQTT协议---CONNECT

    什么是MQTT 1 1简介 MQTT的中文含义 消息队列遥测传输 MQTT的英文 Message Queuing Telemetry Transport 它是基于TCP IP协议 为硬件性能低下的远程设备和网络情况糟糕的情况下设计发布的发布
  • 邻接表的存储

    include
  • 计算机网络——TCP三次握手详解为什么两次不行

    文章目录 1 TCP报文段结构 2 三次握手 3 SYN洪泛攻击 4 为什么是 三次 TCP是面向连接的 connection oriented 即收发双方在发送数据之前 必须首先建立一个连接 这样在连接断开之前 就一直使用这个连接传输数据