TCP中的三次握手和四次挥手
TCP中的连接和断开可以说是在面试中经常被问到的问题之一,正好有空就总结一下,首先回顾一下TCP的相关知识点
1. TCP的基础知识
1.1 TCP的基本概念
我们知道TCP是运输层的面向连接的可靠的传输协议。面向连接的,指的就是在两个进程发送数据之前,必须先相互“握手”,确保两进程可以进行连接。并且这个传输是点对点的,即一个TCP连接中只有一个发送方和接收方;可靠的,指的是在任何网络情况下,在TCP传输中数据都将完整的发送到接收方。
1.2 TCP的报文段结构

-
源端口和目的端口:和UDP一样用于多路复用/分解来自或送到上一层
-
序号:一个报文段的序号是整个传送的字节流序列,而不是该报文段的序列
-
确认号:主机正在等待的数据的下一个字节序号
-
数据偏移:指TCP首部的长度,可变。默认长度为20字节
-
窗口:用于流量控制,用于指示接收方愿意接受的字节数量
-
标志字段:
- ACK:当该位为1时,确认号有效
- RST:该位为1时,表示TCP连接中出现异常必须强制断开连接
- SYC:该位为1时,开始建立连接,并且序号字段进行序列号初始值的设定
- FIN:该位为1时,断开连接,通信双方相互交换FIN位置为1的TCP段后断开连接
2. TCP连接
2.1 什么是连接(connection)和会话(Session)
连接是数据传输双方的契约,在设计上,连接是一种传输数据的行为,具体来说,数据收发双方的内存中都建立一个用于维护数据传输状态的对象,比如TCP 的连接组成包括一台主机上的缓存、变量和与进程连接的套接字,以及另外一台主机上的缓存、变量和与进程连接的套接字。(由端口号和IP地址组成)所以连接是网络行为状态的记录
而会话是应用的行为,比如说你在微信上给人发消息,打开应用聊天窗口和对方聊天是一个会话,但是连接只有在进行发消息、语音的时候连接才开启。其他不发消息和语音时,连接可能暂时断开,但是只要不关聊天窗口,会话时一直存在的。
总结而言,会话是应用层的概念,连接是传输层的概念,正是因为如此,在 TCP 连接的时候需要握手建立连接。
3. TCP连接建立
3.1 TCP 协议中的基本操作
也就是报文段的标志字段的含义和功能:
- SYN(Synchronization):请求同步,一个 Host 主动向另外一个 Host 发起连接。当 SYN=1,ACK=0 时,表示这是一个请求建立连接的报文段;当 SYN=1,ACK=1 时,表示对方同意建立连接
- PSH(Push): 数据推送,一个 Host 主动向另外一个 Host 发送数据
- FIN(Finish): 请求完成,一个 Host 主动断开请求,如果 FIN=1,表示数据已经发送完成,可以释放连接。
- ACK:表示前面的确认号字段是否有效。ACK=1 时表示有效。只有当 ACK=1 时,前面的确认号字段才有效。TCP 规定,连接建立后,ACK 必须为 1
- RST:表示是否重置连接。如果 RST=1,说明 TCP 连接出现了严重错误(如主机崩溃),必须释放连接,然后再重新建立连接。

如图,开始时,两个端口都是出于closed状态,当服务器端口变成listen时,监听端口,是否有数据传来。
-
第一步:客户端向服务端发送一个特殊的TCP报文段。客户端进入SYN_SENT状态这个报文段有以下特点:
- 不包含应用层数据,封装在一个IP数据报中发送给服务器
- SYN为1(此步是ACK唯一可为0处,其他时间均为1)
- 序号段有一个随机生成的初始序号(client_isn)
-
第二步:服务器端收到上步客户端的报文段后,同时为该TCP连接分配TCP缓存和变量,并向该客户发送允许连接的报文段。服务器进入SYN_RCVD状态,这个报文段特点有:
- 不包含应用层数据
- SYN为1,ACK为1
- 确认号段被置为client_isn + 1,序号段被置为server_isn
-
第三步:客户端收到上步服务端的报文段后,客户端为该连接分配缓存和变量,同时客户端向服务器端发送报文段,这个报文端特点有:
- 可以包含应用层数据
- SYN为0,ACK为1
- 确认号段被置为server_isn + 1
两端进入ESTABLISHED状态,连接建立
4. TCP连接断开
若客户端决定要关闭该连接(服务器端也可以发起关闭)

- 第一次:客户端发送带有FIN被置为1的报文段,进入FIN_WAIT_1状态,并等待一个来自服务器的带有确认的TCP报文段。
- 第二次:服务器端收到该报文段后,向客户端发送一个确认ACK报文段,进入CLOSE_WAIT状态。
- 第三次:服务器端处理完数据后向客户端发送FIN被置为1的报文段,进入LAST_ACK状态。
- 第四次:客户端收到服务器端的FIN报文段后,向服务器端发送一个确认ACK报文段,进入TIME_WAIT状态,服务器接收到该ACK报文段后关闭,客户端在经过2MSL(与具体实现有关,典型值是20s、1分钟或2分钟)等待后关闭。
5. 关于TCP连接的面试题
5.1 如何唯一确定一个TCP连接
可以通过四个变量来确定唯一的TCP连接:源地址、源端口、目标地址、目标端口来唯一确定一个TCP连接。其中源地址和目标地址的字段在IP头部,作用是通过IP协议发送报文给哪个主机;源端口和目标端口是在TCP首部,作用是通过TCP协议发送主机中的哪个进程。
5.2 UDP和TCP有什么区别
两者的区别
- UDP面向无连接,利用IP提供无连接的传输数据服务
- UDP可以支持一对多、一对一、多对多的交互通信
- UDP不保证可靠交付数据,传输过程中可能会丢包
- UDP首部只有固定的8字节;TCP首部最短20字节,能够变化
应用场景
- UDP用于包总量较少的通信,如DNS、SNMP;还有视频、音频等多媒体通信,以及广播通信等等
- TCP用于需要保证可靠性数据交付的场景,比如FTP、HTTP
5.3 为什么是三次握手?
为什么TCP连接建立过程中不是两次或者四次,三次就是最优解了吗?首先来看看两次握手建立连接会发生什么。
两次握手
如果连接过程是两次握手来建立,在理想的网络环境下是可以完成通信建立的,但是现实的网络环境很复杂,有时候会导致历史的报文段比新的报文段先到达服务器端,这时,如果没有第三次握手,就会造成无法同步序列号情况的发生。举个例子,客户端发送新SYN报文段的序号是100,网络环境中有旧的SYN报文端的序号是80,然而现在旧的先到达服务器端,那么服务器端则会返回一个确认号为81的SYN+ACK报文段,这个时候客户端接收到的报文段和预期报文段会不一致,就会造成无法同步序列号,达不到TCP可靠运输的效果,也会浪费资源。那么如果有第三次握手,这时客户端会反馈一个RST报文段,终止这次连接,等待新的SYN到来,这样保证数据的可靠性传输。
四次握手

四次握手可以对比四次挥手,客户端和服务器端都要分别发送SYN和ACK报文段,来表示之前的SYN报文已经被成功接收。
然而四次握手可以简化成三次,第二、三次可以优化成一次。所以三次是保证可靠性传输连接的最优解。
5.4 什么是SYN 泛洪?如何避免
SYN泛洪攻击通过发送大量的TCP SYN报文段,而不完成第三次握手的步骤。因为大量的SYN报文段的发送,服务器不断为这些半开连接分配资源,导致服务器的连接资源被消耗殆尽。
如何避免,现在有一种有效的防御系统,称为SYN cookie,它是这样工作的:
- 当服务器接收到一个SYN报文段时,它并不知道该报文段是来自一个合法用户还是SYN泛洪攻击的一部分。因此服务器不会为该报文段生成一个半开连接。相反,服务器会生成一个初始TCP序列号cookie值(由目的IP地址与端口号以及仅有该服务器知道的秘密数的一个复杂函数),并发送给客户端
- 如果客户是合法的,将会返回一个ACK报文段。而且当服务器收到该ACK后,需要验证该ACK是与前面发送的SYN相对应,并生成一个具有套接字的全开的连接。如果没有返回一个ACK报文段,则初始的SYN并没有对服务器产生危害,因为服务器也没为它分配任何资源。
5.5 为什么是四次挥手
四次挥手中双方发送了FIN报文段,所以在客户端发送FIN后,服务器端接收到后首先会回一个ACK应答报文,因为此时服务器端可能还有数据没发送完,所以在服务端数据处理完后,才发送FIN报文段给客户端表示现在可以关闭连接。正是因为这个等待过程,使得比三次握手多一次。
5.6 如果已经建立了连接,客户端出现故障了怎么办?
TCP有一个机制是保活机制:定义在一个时间段内,如果没有任何连接相关的活动,TCP保活机制则开始作用,每隔一个时间间隔会发送一个探测报文,该探测报文包含的数据很少,如果连续几个探测报文都没有得到响应,说明该TCP连接已经死亡。
客户端的故障也分为这几种:
- 对端系统正常回复探测报文,TCP保活时间重置,等待下一个保活时间到来,TCP连接正常运行。
- 对端程序崩溃并重启,此时可以对探测报完进行响应,但是没有连接的有效消息,序列不符合,最后会产生RST报文,这时连接被重置。
- 对端程序彻底崩溃,无法响应探测报,经过几次连续无响应后TCP会报告此连接已经死亡
5.7 为什么需要TIME_WAIT状态
首先要说明,只有主动发起关闭连接的一方才会有TIME_WAIT状态,那么为什么会有TIME_WAIT状态,这时因为在服务端关闭后,可能还会有其他的数据报未到达客户端,所以需要再等待一段时间。一般这个时间是2MSL时间,也就是报文段在两端传输的最大往返时间。
TIME_WAIT状态太多也会导致占用过多的端口资源,会导致无法创建新的连接
参考博客:
https://mp.weixin.qq.com/s/tH8RFmjrveOmgLvk9hmrkw
相关文章:
TCP中的三次握手和四次挥手
TCP中的连接和断开可以说是在面试中经常被问到的问题之一,正好有空就总结一下,首先回顾一下TCP的相关知识点 1. TCP的基础知识 1.1 TCP的基本概念 我们知道TCP是运输层的面向连接的可靠的传输协议。面向连接的,指的就是在两个进程发送数据…...
NAO.99b海潮模型的详解教程
NAO.99b模型是由日本国家天文台开发的全球潮汐模式,基于二维非线性浅水方程。该模型具有较高的分辨率,网格间距为0.50.5,网格数为720360,覆盖的经度范围为0.25~359.75E,纬度范围为89.75S~89.75N…...
Plantuml之JSON数据语法介绍(二十五)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...
迅为龙芯2K1000开发板虚拟机 ubuntu 更换下载源
Ubuntu 系统软件的下载安装我们通常使用命令“apt-get” , 该命令可以实现软件自动下载, 安装, 配置。 该命令采用客户端/服务器的模式, 我们的 Ubuntu 系统作为客户端, 当需要下载软件的时候就向服务器发起请求&#…...
你好!Apache Seata
北京时间 2023 年 10 月 29 日,分布式事务开源项目 Seata 正式通过 Apache 基金会的投票决议,以全票通过的优秀表现正式成为 Apache 孵化器项目! 根据 Apache 基金会邮件列表显示,在包含 13 个约束性投票 (binding votes) 和 6 个…...
RFC6749-OAuth2.0
前言 最近在项目中需要实现SSO(单点登录)功能,以实现一处注册,即可在任何平台之间登录的功能。我们项目中并没有直接对接第三方认证系统而是通过集成keycloak 完成一系类安全协议的对接工作。如果我们在代码级别自己完成各种安全协议的对接是一项十分大的工程。不仅要走统一的…...
【代码解析】代码解析之生成token(1)
本篇文章主要解析上一篇:代码解析之登录(1)里的第8行代码调用 TokenUtils 类里的genToken 方法 https://blog.csdn.net/m0_67930426/article/details/135327553?spm1001.2014.3001.5501 genToken方法代码如下: public static S…...
牛客网SQL训练5—SQL大厂面试真题
文章目录 一、某音短视频1.各个视频的平均完播率2.平均播放进度大于60%的视频类别3.每类视频近一个月的转发量/率4.每个创作者每月的涨粉率及截止当前的总粉丝量5.国庆期间每类视频点赞量和转发量6.近一个月发布的视频中热度最高的top3视频 二、用户增长场景(某度信…...
kubeadm来搭建k8s集群。
我们采用了二进制包搭建出的k8s集群,本次我们采用更为简单的kubeadm的方式来搭建k8s集群。 二进制的搭建更适合50台主机以上的大集群,kubeadm更适合中小型企业的集群搭建 主机配置建议:2c 4G 主机节点 IP …...
【java爬虫】使用element-plus进行个股详细数据分页展示
前言 前面的文章我们讲述了获取详细个股数据的方法,并且使用echarts对个股的价格走势图进行了展示,本文将编写一个页面,对个股详细数据进行展示。别问涉及到了element-plus中分页的写法,对于这部分知识将会做重点讲解。 首先看一…...
Python使用余弦相似度比较两个图片
为了使用余弦相似度来找到与样例图片相似的图片,我们需要先进行一些预处理,然后计算每两张图片之间的余弦相似度。以下是一个简单的实现: 读取样例图片和目标文件夹中的所有图片。对每张图片进行预处理,例如灰度化、降噪等。计算…...
树莓派4B-Python使用PyCharm的SSH协议在电脑上远程编辑程序
目录 前言一、pycharm的选择二、添加SSH的解释器使用总结 前言 树莓派的性能始终有限,不好安装与使用高级一点的程序编辑器,如果只用thonny的话,本人用得不习惯,还不如PyCharm,所以想着能不能用电脑中的pycharm来编写…...
Servlet的自动加载、ServletConfig对象、ServletContext对象
一、 Servlet的自动加载 默认情况下,第一次访问servlet的时候,创建servlet对象。如果servlet构造函数里面的代码或者init方法里面的代码比较多,就会导致用户第一次访问servlet的时候比较慢。这个时候,我们可以改变servlet对象的创…...
Vue - Class和Style绑定详解
1. 模板部分 <template><div><!-- Class 绑定示例 --><div :class"{ active: isActive, text-danger: hasError }">Hello, Vue!</div><!-- Class 绑定数组示例 --><div :class"[activeClass, errorClass]">Cla…...
适用于 Windows 的 7 个顶级视频转换器 – 流畅的视频转换体验!
对于任何想要增强视频转换体验的人来说,视频转换器都是必不可少的工具。无论您是需要转换视频文件格式以实现兼容性,还是只是想优化视频以获得更好的质量,可靠的视频转换器都可以使该过程无缝且高效。在这篇博文中,我们将探讨适用…...
Vue3全局属性app.config.globalProperties
文章目录 一、概念二、实践2.1、定义2.2、使用 三、最后 一、概念 一个用于注册能够被应用内所有组件实例访问到的全局属性的对象。点击【前往】访问官网 二、实践 2.1、定义 在main.ts文件中设置app.config.globalPropertie import {createApp} from vue import ElementPl…...
单片机开发--keil5
一.keil5 Keil uVision5是一个集成开发环境(IDE),用于对嵌入式系统中的微控制器进行编程。它是一个软件套件,包括源代码编辑器、项目经理、调试器以及微控制器开发、调试和编程所需的其他工具。Keil uVision5 IDE主要用于对基于A…...
<JavaEE> TCP 的通信机制(三) -- 滑动窗口
目录 TCP的通信机制的核心特性 四、滑动窗口 1)什么是滑动窗口? 2)滑动窗口的作用是什么? 3)批量传输出现丢包如何处理? 1> 接收端ACK丢包 2> 发送端数据包丢包 4)适用性 TCP的通…...
听GPT 讲Rust源代码--library/portable-simd
File: rust/library/portable-simd/crates/core_simd/examples/spectral_norm.rs spectral_norm.rs是一个示例程序,它展示了如何使用Portable SIMD库中的SIMD(Single Instruction Multiple Data)功能来实现频谱规范化算法。该示例程序是Rust源…...
CMake入门教程【基础篇】CMake+Minggw构建项目
文章目录 Minggw是什么Minggw下载CMake下载安装第1步:下载CMake第2步:安装CMake 如何构建和编译项目:使用CMake和MinGW总结 Minggw是什么 MinGW(Minimalist GNU for Windows)是一个免费的软件开发环境,旨在…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
