【网络编程】五、三次握手 四次挥手

news2025/5/13 11:21:39

文章目录

  • Ⅰ. 三次握手
  • Ⅱ. 建立连接后的通信
  • Ⅲ. 四次挥手

在这里插入图片描述

Ⅰ. 三次握手

在这里插入图片描述

​ 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+1ack = 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 = vack = u+1 报文序号,这时的 TCP 连接处于半关闭的状态

​ 之后客户端收到服务端的确认关闭之后,会进入 FIN_WAIT2 状态;而服务端之所以进入 CLOSE_WAIT 状态,是因为可能此时服务端还有之前没处理完的数据,在这个状态之内会 将这些剩余的数据都发送给客户端,而客户端也依然会接收,相当于客户端之前调用的 close() 只关闭了写端,而这个状态可能会持续一段时间直到数据发完!

​ 3、当服务端发送完剩余数据之后,服务端的操作系统就会通知对应的进程,告诉其该调用 close() 函数了,所以该服务端进程就调用了 close() 函数进行关闭套接字(因为 TCP 连接时全双工通信,所以双方都得发起断开连接请求),此时会向客户端发送 FIN 报文段表示断开连接。

​ 假设此时服务端的序号为 w(因为前面传输剩余数据之后可能序号发送了变化),则服务端会在报文中携带 seq = wack = 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 中默认 2MSL60

​ 至于为什么要设置这个 2MSL 值,是因为有可能客户端发出去的 ACK 报文丢失了,在这段时间内服务端收不到应答,就可以进行超时重传,重传上面的 FIN + ACK 报文段,一般来说,重传之后这个时间等待计数器是会重置的!如果没有 2MSL 的话,服务端就不知道是否要断开连接,则一直等待着客户端的应答,浪费了资源!

​ 另外,当 服务端重传第三次挥手报文的次数达到 2 时, 达到了最大重传次数,于是再等待一段时间(时间为上一次超时时间的 2 倍),如果还是没能收到客户端的第四次挥手(ACK 报文),那么服务端就会断开连接。

​ 而 客户端 在收到第三次挥手后,就会进入 TIME_WAIT 状态,开启时长为 2MSL 的定时器,如果途中再次收到第三次挥手(FIN 报文)后,就会重置定时器,当等待 2MSL 时长后,客户端就会断开连接。如下图所示:

​ 5、而当服务端收到了确认应答之后,就会直接进入 CLOSED 状态,释放连接!

在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从 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文件格式。 …

从 JIT 即时编译一直讲到CGI|FastGGI|WSGI|ASGI四种协议的实现细节

背景 我一度理解错了这个东西,之前没有AI的时候,也没深究过,还觉得PHP8支持了常驻内存的运行的错误理解,时至今日再来看这个就很清晰了。 另外,早几年对以上4个协议,我也没搞懂,时至今日&…

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中的中断是设备主动发起的…

.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…

【日撸 Java 三百行】Day 11(顺序表(一))

目录 Day 11:顺序表(一) 一、关于顺序表 二、关于面向对象 三、代码模块分析 1. 顺序表的属性 2. 顺序表的方法 四、代码及测试 拓展: 小结 Day 11:顺序表(一) Task: 在《数…

软考 系统架构设计师系列知识点之杂项集萃(55)

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

保持Word中插入图片的清晰度

大家有没有遇到这个问题,原本绘制的高清晰度图片,插入word后就变模糊了。先说原因,word默认启动了自动压缩图片功能,分享一下如何关闭这项功能,保持Word中插入图片的清晰度。 ①在Word文档中,点击左上角的…

Linux复习笔记(三) 网络服务配置(web)

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

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 控件的行背景颜色&#xff0c;需要通过自绘&#xff08;Owner-Draw&#xff09;机制实现。以下是详细的实现方法&#xff1a; 方法一&#xff1a;通过自绘&#xff08;Owner-Draw&#xff09;实现 步骤 1&#xff1a;启用自绘属性 在对话框设计器中选…

SpringBoot+Dubbo+Zookeeper实现分布式系统步骤

SpringBootDubboZookeeper实现分布式系统 一、分布式系统通俗解释二、环境准备&#xff08;详细版&#xff09;1. 软件版本2. 安装Zookeeper&#xff08;单机模式&#xff09; 三、完整项目结构&#xff08;带详细注释&#xff09;四、手把手代码实现步骤1&#xff1a;创建父工…

Linux进程10-有名管道概述、创建、读写操作、两个管道进程间通信、读写规律(只读、只写、读写区别)、设置阻塞/非阻塞

目录 1.有名管道 1.1概述 1.2与无名管道的差异 2.有名管道的创建 2.1 直接用shell命令创建有名管道 2.2使用mkfifo函数创建有名管道 3.有名管道读写操作 3.1单次读写 3.2多次读写 4.有名管道进程间通信 4.1回合制通信 4.2父子进程通信 5.有名管道读写规律&#xff…