【网络编程】五、三次握手 四次挥手
文章目录
- Ⅰ. 三次握手
- Ⅱ. 建立连接后的通信
- Ⅲ. 四次挥手

Ⅰ. 三次握手
1、首先双方都是处于未通信的状态,也就是关闭状态 CLOSE
。
2、因为服务端是为了服务客户端的,所以它会提前调用 listen()
函数进行对客户端请求的监听。
3、接着客户端就想访问服务端,所以通过 connect()
函数主动发起请求报文,此时报文中将 SYN
字段设为 1
,表示请求建立连接,并且选择一个初始化序号 seq = x
,(这是因为 TCP
规定 SYN
报文段不能携带数据,但要消耗掉一个序号)此时客户端就进入了 SYN_SEND
状态,等待服务端的回应。
4、服务端收到了客户端发来的 SYN
报文之后,会向客户端发送给 SYN + ACK
都置一的报文段表示同意建立连接,同时携带确认号为 ack = x+1
,并且也为自己选择一个初始序号 seq = y
。最后调用 accept()
函数进行 阻塞,直到操作系统收到了来自客户端的确认应答,然后进入 SYN_RECV
状态!其实服务端收到的这条请求,会将这条请求放到一个 半连接队列 中等待处理。(这个后面会讲)
5、接着如果没有意外的话,客户端就收到了同意连接的应答,进入 ESTABLISHED
状态。同时为了让服务端知道自己知道了应答,就向服务端发送最后一个 ACK
报文,表示确认应答,同时携带 seq = x+1
和 ack = y+1
。(这是因为 TCP
规定 ACK
报文段可以携带数据,但如果不携带数据的话则不消耗序号)
除此之外,客户端应用层一直阻塞的 connect()
函数也返回了,通过其返回值可以判断是否建立连接成功!
6、最后服务端也收到了来自客户端的确认应答,便进入了 ESTABLISHED
状态,此时服务端应用层一直阻塞的 accept()
函数也 返回了一个新分配的文件描述符,是一个用于与客户端进行通信套接字!
实际上需要强调的一点是这个新分配的文件描述符是从一个叫做 完全连接队列 中也就是 accpet
队列 中取出来的,其是需要一定的排队时间的!这也是 accept()
函数的第二个参数 backlog
的含义,也就是完全连接队列的最大长度,后面我们还会详细讲!
Ⅱ. 建立连接后的通信
一般来说网络编程中,我们可以使用两套对应的接口来通信,都是可以的,分别是
send()
、recv()
和write()
、read()
函数,它们的区别我们之前在讲套接字接口的时候就提到过,一般网络编程中会使用send()
、recv()
,而write()
、read()
函数多用于文件操作中(虽然网络编程本质也是文件操作=-=),但是它们其实都是通用的,所以要是看到别人用上面两套接口进行网络编程的话,都是可以的! 而我们这里讲的主要是前一套!
在通信过程中,无论是客户端还是服务端,它们都是处于 ESTABLISHED
状态的,这是不变的!
如果某一端想发送数据了,那么直接调用 send()
函数进行发送,因为我们前面实现过 tcp
服务器,所以我们知道一般服务器都是多线程、线程池版本,实现读写分离的,所以一般收发是分开的(本质是因为有两个缓冲区),很体现 全双工 的通信特点,所以此时服务端肯定是有线程或者进程在调用着 recv()
函数阻塞着读取客户端发来的信息的!如果收到了消息,那么 recv()
就会停止阻塞,然后返回对应的字节数!
如果说对方是断开连接请求的话,recv()
就会返回一个 0
表示要断开连接啦,此时就会进入四次挥手的过程,这个下面会讲!
除此之外需要提醒的是,一般来说服务端是不会主动向发送信息,除非是回应业务处理,最能体现这种情况的就是 http
协议啦,而相反会经常主动给客户端发送数据的大多都是需要实时处理的业务,比如说游戏画面,就像我们学过的 websocket
协议,就是一个样例!
Ⅲ. 四次挥手
1、首先客户端应用层调用了 close()
函数之后,会向服务端发送 FIN
报文段,其中因为上面可能通信发送了其它数据,所以这里我们用 seq = u
表示当前的报文序号,并且进入 FIN_WAIT1
状态等待服务端回应。
2、此时服务端因为一直调用着 recv()
函数接收数据,此时突然 recv()
函数返回 0
,表示客户端要断开连接了,所以服务端就进入了 CLOSE_WAIT
状态,并向客户端发送 ACK
报文段表示确认断开连接,并且携带 seq = v
和 ack = u+1
报文序号,这时的 TCP
连接处于半关闭的状态!
之后客户端收到服务端的确认关闭之后,会进入 FIN_WAIT2
状态;而服务端之所以进入 CLOSE_WAIT
状态,是因为可能此时服务端还有之前没处理完的数据,在这个状态之内会 将这些剩余的数据都发送给客户端,而客户端也依然会接收,相当于客户端之前调用的 close()
只关闭了写端,而这个状态可能会持续一段时间直到数据发完!
3、当服务端发送完剩余数据之后,服务端的操作系统就会通知对应的进程,告诉其该调用 close()
函数了,所以该服务端进程就调用了 close()
函数进行关闭套接字(因为 TCP
连接时全双工通信,所以双方都得发起断开连接请求),此时会向客户端发送 FIN
报文段表示断开连接。
假设此时服务端的序号为 w
(因为前面传输剩余数据之后可能序号发送了变化),则服务端会在报文中携带 seq = w
和 ack = u+1
(重复发一次),然后服务端就进入了 LAST_ACK
状态等待客户端的确认应答。
4、客户端收到了服务端的连接释放报文段之后,必须对此发出确认。所以会向服务端发送 ACK
报文,顺便携带自己的序号 seq = u+1
和确认号 ack = w+1
,然后就进入了 TIME_WAIT
状态!
注意,此时进入 TIME_WAIT
状态之后是不会立刻释放连接的,还需要经过 时间等待计时器(TIME-WAIT timer
)设置的时间 2MSL
之后才会进入 CLOSED
状态,而 MSL
时间叫做最长报文段寿命(Maximum Segment Lifetime
)。
一般这个时间是可以自行设定的,根据 RFC793
规定建议设为 2
分钟,所以来回总共就是 4
分钟 的等待时间,不过一般会根据具体的情况使用更小的 MSL
值,在 linux
中默认 2MSL
是 60
秒。
至于为什么要设置这个
2MSL
值,是因为有可能客户端发出去的ACK
报文丢失了,在这段时间内服务端收不到应答,就可以进行超时重传,重传上面的FIN + ACK
报文段,一般来说,重传之后这个时间等待计数器是会重置的!如果没有2MSL
的话,服务端就不知道是否要断开连接,则一直等待着客户端的应答,浪费了资源! 另外,当 服务端重传第三次挥手报文的次数达到
2
时, 达到了最大重传次数,于是再等待一段时间(时间为上一次超时时间的2
倍),如果还是没能收到客户端的第四次挥手(ACK
报文),那么服务端就会断开连接。 而 客户端 在收到第三次挥手后,就会进入
TIME_WAIT
状态,开启时长为2MSL
的定时器,如果途中再次收到第三次挥手(FIN
报文)后,就会重置定时器,当等待2MSL
时长后,客户端就会断开连接。如下图所示:
5、而当服务端收到了确认应答之后,就会直接进入 CLOSED
状态,释放连接!
相关文章:

【网络编程】五、三次握手 四次挥手
文章目录 Ⅰ. 三次握手Ⅱ. 建立连接后的通信Ⅲ. 四次挥手 Ⅰ. 三次握手 1、首先双方都是处于未通信的状态,也就是关闭状态 CLOSE。 2、因为服务端是为了服务客户端的,所以它会提前调用 listen() 函数进行对客户端请求的监听。 3、接着客户端就…...
【类拷贝文件的运用】
常用示例 当我们面临将文本文件分成最大大小块的时,我们可能会尝试编写如下代码: public class TestSplit {private static final long maxFileSizeBytes 10 * 1024 * 1024; // 默认10MBpublic void split(Path inputFile, Path outputDir) throws IOException {…...

从 AGI 到具身智能体:解构 AI 核心概念与演化路径全景20250509
🤖 从 AGI 到具身智能体:解构 AI 核心概念与演化路径全景 作者:AI 应用实践者 在过去的几年中,AI 领域飞速发展,从简单的文本生成模型演进为今天具备复杂推理、感知能力的“智能体”系统。本文将从核心概念出发&#x…...

Docker Compose 的历史和发展
这张图表展示了Docker Compose从V1到V2的演变过程,并解释了不同版本的Compose文件格式及其支持情况。以下是对图表的详细讲解: Compose V1 No longer supported: Compose V1已经不再支持。Compose file format 3.x: 使用了版本3.x的Compose文件格式。 …...
ARMV8 RK3399 u-boot TPL启动流程分析 --crt0.S
上一篇介绍到start.S 最后一个指令是跳转到_main, 接下来分析 __main 都做了什么 arch/arm/lib/crt0.S __main 注释写的很详细,主要分为5步 1. 准备board_init_f的运行环境 2. 跳转到board_init_f 3. 设置broad_init_f 申请的stack 和 GD 4. 完整u-boot 执行re…...

从 JIT 即时编译一直讲到CGI|FastGGI|WSGI|ASGI四种协议的实现细节
背景 我一度理解错了这个东西,之前没有AI的时候,也没深究过,还觉得PHP8支持了常驻内存的运行的错误理解,时至今日再来看这个就很清晰了。 另外,早几年对以上4个协议,我也没搞懂,时至今日&…...
Vue.js 页面切换空白与刷新 404 问题深度解析
在使用 Vue.js 开发单页应用 (SPA) 的过程中,开发者经常会遇到两个常见问题:页面切换时出现短暂的空白屏幕,以及刷新页面时返回 404 错误。这两个问题不仅影响用户体验,还可能阻碍项目的正常上线。本文将深入探讨这两个问题的成因…...

CSS3 遮罩
在网页设计中,我们经常需要实现一些特殊的视觉效果来增强用户体验。CSS3 遮罩(mask)允许我们通过控制元素的可见区域来创建各种精美的视觉效果。本文将带你全面了解 CSS3 遮罩的功能和应用。 什么是 CSS3 遮罩? CSS3 遮罩是一种…...

ResNet残差神经网络的模型结构定义(pytorch实现)
ResNet残差神经网络的模型结构定义(pytorch实现) ResNet‑34 ResNet‑34的实现思路。核心在于: 定义残差块(BasicBlock)用 _make_layer 方法堆叠多个残差块按照 ResNet‑34 的通道和层数配置来搭建网络 import torch…...

uniapp|商品列表加入购物车实现抛物线动画效果、上下左右抛入、多端兼容(H5、APP、微信小程序)
以uniapp框架为基础,详细解析商品列表加入购物车抛物线动画的实现方案。通过动态获取商品点击位置与购物车坐标,结合CSS过渡动画模拟抛物线轨迹,实现从商品图到购物车图标的动态效果。 目录 核心实现原理坐标动态计算抛物线轨迹模拟动画元素控制代码实现详解模板层设计脚本…...

谈AI/OT 的融合
过去的十几年间,工业界讨论最多的话题之一就是IT/OT 融合,现在,我们不仅要实现IT/OT 的融合,更要面向AI/OT 的融合。看起来不太靠谱,却留给我们无限的想象空间。OT 领域的专家们不要再当“九斤老太”,指责这…...

USB传输模式
USB有四种传输模式: 控制传输, 中断传输, 同步传输, 批量传输 1. 中断传输 中断传输一般用于小批量, 非连续的传输. 对实时性要求较高. 常见的使用此传输模式的设备有: 鼠标, 键盘等. 要注意的是, 这里的 “中断” 和我们常见的中断概念有差异. Linux中的中断是设备主动发起的…...
Tomcat的`context.xml`配置详解!
全文目录: 开篇语前言一、context.xml 文件的基本结构二、常见的 context.xml 配置项1. **数据源(DataSource)配置**示例: 2. **日志配置**示例: 3. **设置环境变量(Environment Variables)**示…...
MapReduce 的工作原理
MapReduce 是一种分布式计算框架,用于处理和生成大规模数据集。它将任务分为两个主要阶段:Map 阶段和 Reduce 阶段。开发人员可以使用存储在 HDFS 中的数据,编写 Hadoop 的 MapReduce 任务,从而实现并行处理1。 MapReduce 的工作…...

.NET10 - 尝试一下Open Api的一些新特性
1.简单介绍 .NET9中Open Api有了很大的变化,在默认的Asp.NET Core Web Api项目中,已经移除了Swashbuckle.AspNetCore package,同时progrom中也变更为 builder.Servers.AddOpenApi() builder.Services.MapOpenApi() 2025年微软将发布…...

RabbitMQ 工作模式
RabbitMQ 一共有 7 中工作模式,可以先去官网上了解一下(一下截图均来自官网):RabbitMQ 官网 Simple P:生产者,要发送消息的程序;C:消费者,消息的接受者;hell…...

基于C++的多线程网络爬虫设计与实现(CURL + 线程池)
在当今大数据时代,网络爬虫作为数据采集的重要工具,其性能直接决定了数据获取的效率。传统的单线程爬虫在面对海量网页时往往力不从心,而多线程技术可以充分利用现代多核CPU的计算能力,显著提升爬取效率。本文将详细介绍如何使用C…...
Android11.0 framework第三方无源码APP读写断电后数据丢失问题解决
1.前言 在11.0中rom定制化开发中,在某些产品开发中,在某些情况下在App用FileOutputStream读写完毕后,突然断电 会出现写完的数据丢失的问题,接下来就需要分析下关于使用FileOutputStream读写数据的相关流程,来实现相关 功能 2.framework第三方无源码APP读写断电后数据丢…...
国产大模型「五强争霸」:决战AGI,谁主沉浮?
引言 中国AI大模型市场正经历一场史无前例的洗牌!曾经“百模混战”的局面已落幕,字节、阿里、阶跃星辰、智谱和DeepSeek五大巨头强势崛起,形成“基模五强”新格局。这场竞争不仅是技术实力的较量,更是资源、人才与生态的全面博弈。…...
【Python 基础语法】
Python 基础语法是编程的基石,以下从核心要素到实用技巧进行系统梳理: 一、代码结构规范 缩进规则 使用4个空格缩进(PEP 8标准)缩进定义代码块(如函数、循环、条件语句) def greet(name):if name: # 正确缩…...

【日撸 Java 三百行】Day 11(顺序表(一))
目录 Day 11:顺序表(一) 一、关于顺序表 二、关于面向对象 三、代码模块分析 1. 顺序表的属性 2. 顺序表的方法 四、代码及测试 拓展: 小结 Day 11:顺序表(一) Task: 在《数…...
path环境变量满了如何处理,分割 PATH 到 Path1 和 Path2
要正确设置 Path1 的值,你需要将现有的 PATH 环境变量 中的部分路径复制到 Path1 和 Path2 中。以下是详细步骤: 步骤 1:获取当前 PATH 的值 打开环境变量窗口: 按 Win R,输入 sysdm.cpl,点击 确定。在 系…...

软考 系统架构设计师系列知识点之杂项集萃(55)
接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(54) 第89题 某软件公司欲开发一个Windows平台上的公告板系统。在明确用户需求后,该公司的架构师决定采用Command模式实现该系统的界面显示部分,并设计UML类图如…...

保持Word中插入图片的清晰度
大家有没有遇到这个问题,原本绘制的高清晰度图片,插入word后就变模糊了。先说原因,word默认启动了自动压缩图片功能,分享一下如何关闭这项功能,保持Word中插入图片的清晰度。 ①在Word文档中,点击左上角的…...
Web应用开发指南
一、引言 随着互联网的迅猛发展,Web应用已深度融入日常生活的各个方面。为满足用户对性能、交互与可维护性的日益增长的需求,开发者需要一整套高效、系统化的解决方案。在此背景下,前端框架应运而生。不同于仅提供UI组件的工具库,…...
贝叶斯算法
贝叶斯算法是一类基于贝叶斯定理的机器学习算法,它们在分类任务中表现出色,尤其在处理具有不确定性和 probabilistic 关系的数据时具有独特优势。本文将深入探讨贝叶斯算法的核心原理、主要类型以及实际应用案例,带你领略贝叶斯算法在概率推理…...

Linux复习笔记(三) 网络服务配置(web)
遇到的问题,都有解决方案,希望我的博客能为你提供一点帮助。 二、网络服务配置 2.3 web服务配置 2.3.1通信基础:HTTP协议与C/S架构(了解) HTTP协议的核心作用 Web服务基于HTTP/HTTPS协议实现客户端ÿ…...

springboot旅游小程序-计算机毕业设计源码76696
目 录 摘要 1 绪论 1.1研究背景与意义 1.2研究现状 1.3论文结构与章节安排 2 基于微信小程序旅游网站系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统…...

uniapp自定义导航栏搭配插槽
<uni-nav-bar dark :fixed"true" shadow background-color"#007AFF" left-icon"left" left-text"返回" clickLeft"back"><view class"nav-bar-title">{{ navBarTitle }}</view><block v-slo…...

MFC listctrl修改背景颜色
在 MFC 中修改 ListCtrl 控件的行背景颜色,需要通过自绘(Owner-Draw)机制实现。以下是详细的实现方法: 方法一:通过自绘(Owner-Draw)实现 步骤 1:启用自绘属性 在对话框设计器中选…...