当前位置: 首页 > news >正文

【网络面试(5)】收发数据及断开服务器(四次挥手)

 前面了解到服务器和客户端在创建套接字,建立连接后,就可以进入到下一步,双发可以互相发送和接收数据,本篇博客就来学习一下这个过程。
 我们印象里,发送数据应该是我们在浏览器输入网址,敲击回车的一瞬间,发送动作就完成了,回头服务器处理完成将数据发送客户端,浏览器解析出来,这就是反过来接收的过程。

1. 发送数据

 由浅入深,了解这个大体过程,我们先来看看发送数据的简单过程。对于浏览器,他没有办法直接向网络中发送数据,而是要将http请求委托给协议栈(操作系统的网络控制软件)来发送。但实际上,在计算机中,并不是只有浏览器会发送网络请求,QQ、微信等很多应用程序都会执行这个动作。所以协议栈工作就是会接收各种应用程序发送过来的网络请求数据,其实就是一堆的二进制字节数据。

 协议栈在拿到数据后,是不是会直接发送到网络中的呢?必然不是,他在内部会维护一段内存缓冲区,等待下一段数据,然后在某个合适的时机再发送出去。这块内存就是发送数据的专用缓冲区。当然,接收数据的时候也是有一块专用内存的,后面我们再说这个。这里还提到了,合适的时机发送数据,这个时机是根据两个要素来判断的,我们看看是哪两个。

1.1 网络包长度

 第一个因素是跟网络包长度相关的,什么意思呢,对于某些GET请求,要发送的请求内容必然很少,一个网络包就能放得下,但是有些POST请求,比如我要写的这篇博客,经过编码解析,需要很多歌网络包才能放的下,这里就涉及到拆包的概念。

 这里先了解两个网络词汇:MTUMSS

  • MTU: 指的是一个网络包的最大长度,以太网中通常是1500个字节。
  • MSS: MTU中去掉头部之后,所能容纳的数据的最大长度。

在这里插入图片描述

 了解这两个概念,我们在来看下上面说的拆包的概念,即我们发送的某次网络请求,可能是通过1个网络包发送给服务器的,也可能是很多个,决定因素就是MTU和MSS。

 在应用程序将数据发送给协议栈的时候,数据可大可小,协议栈无法决定,如果每次接收到应用程序的一次数据就立即发送出去,必然会导致发送大量小的网络包,网络效率下降。所以,协议栈一般会累积到数据量可以塞满一个网络包的时候再发送出去,即MTU的长度,这就是第一个决定协议栈发送数据的因素。

1.2 发送时间

 决定协议栈 发送数据的第二个因素是时间,为啥呢?我们可以试想一下,如果GET请求的数据长度无法达到一个MTU的长度,协议栈一直等待到一个网络包的数据长度再发出去,必然会产生很大的延迟,给我们卡顿的感觉。所以,某些情况下,即便网络包没有被填满,也会立即把数据发送出去。
 协议栈内部会维护一个计时器,在超过设定的时间阈值后,即便没有达到一个完整网络包数据长度,也会立即发送。一般,这个时间是由协议栈的开发者决定的,不同操作系统的不同版本会有不同实现。

 其实,决定协议栈发送数据的这两个要素,在某些情况下是比较矛盾的,立即发送会导致网络效率下降,等待太久又会造成延迟。过分依靠协议栈来决定发送时机会带来一些问题,所以协议栈也给了应用程序一个选项,来决定是否立即发送。像浏览器这样的会话型应用程序,一般会选择“立即发送”的选项。

2. 确认发送成功以及重发功能的实现

 TCP协议的非常重要的功能就是可以确认通信的一方是否已经成功收到了网络包,如果没有收到,必须具有重发的功能。这个功能的实现就是借助于ACK号和seq序号要进行对方接收确认的操作。

 上文我们说过,在网络请求内容过大的时候,TCP会有拆包的逻辑,那么在拆分的过程中,TCP就会计算好并记录每个网络小包在整个请求内容中处于第几个字节,然后再发送网络包的时候,在TCP头部记录这个字节数(就是seq序号,比如目前是第1个字节),服务器在接收到网络包的时候,会读取这个字节,然后再计算这个网络包MSS的长度(比如网络包数据长度是1000),在确认回复的时候,会将ACK赋值为ACK = 1 + 1000 并返回给客户端。客户端在接收到ACK号的时候就可以确定网络包已经顺利被对方接收,否则就会重试发送。

 我们可以想象一下,客户端在发送下一个网络包的时候,一定是从第1001个字节开始的,于是服务器在收到请求后,可以顺便验证1001是不是和自己最后一次ACK响应的字节数相等,如果相等说明中间没有丢包,如果是2001,说明中间丢失了至少一个网络包。

 这里我们已经提到了ACK和seq,TCP协议可以通过ACK号和序号就可以确认对方是否收到了网络包。我们来看一个虚拟的例子加深一下了解。

在这里插入图片描述

2.1 调整ACK号等待时间

 我们的网络传输并不是一帆风顺的,发生拥塞和抖动的情况是非常常见的。前文我们提到TCP会通过ACK号确认对方已经接收到网络包,但是在网络比较慢的情况下,发送和接收ACK号的平均响应时间就会比较长了,如果客户端在这个时候设置了比较短的等待时间,就会在没收到ACK的情况一直向以太网中发送数据,这对于本来已经繁忙的网络就更加糟糕了,这其实就是TCP的网络包重传。

 通常,当网络包重传发生后,有可能前一个相同网络包的ACK号才返回,这样的重传其实是不必要的。所以,对于等待时间来说,需要设置一个合适的值,这个时间应该是可以动态调整的,而计算方法就是根据过往发送数据的过程中,持续监测ACK号的响应时间,如果ACK号的返回时间变慢,就会响应延长这个等待时间,否则就缩短等待时间。

 除此之外,TCP还是使用了滑动窗口的方式来管理数据发送和ACK号的管理,大体思路就是第一个网络包在发送出去之后,并不是等待当前网络包的ACK号返回才发送下一个,而是直接发送下一个,或者说是下面一系列的网络包,这样的话,发送的等待时间就会被有效的利用起来了。这个过程相对复杂一些,涉及到窗口大小的概念,这个窗口大小就是指接收方网络协议栈中,在当前时间里,剩余的最大缓存空间,也就是能接收的字节数。下图中可以看出来一来一回和滑动窗口的方式,这里不再深入展开,可以查看相关资料。

在这里插入图片描述

3. 接收数据

 在客户端发送完数据的过程后,服务器端就可以接收并处理网络包了,对于单个网络包的处理比较简单,对于客户端拆分后分多次发送的网络包,服务器的TCP协议同样会以相同的方式拼接起来转换成为对应的网络请求,其实就是和客户端处理相反的方式进行的。服务器在处理请求后,就会将相应数据发送给客户端。

 我们可以想一下,客户端的浏览器程序在委托协议栈发送了网络请求后,就处于等待响应结果的状态。这个状态其实是浏览器调用了Socket组件库的read()函数,协议栈会将这个工作挂起,直到服务器数据相应之后,协议栈写入到接收缓冲区中,在这个过程之前,接收缓冲区一直是空的,浏览器就无法处理数据,这个挂起就是我们常说的阻塞过程。这个如果继续延伸的话,会有阻塞式IO,非阻塞式IO,IO多路复用等知识点,在此不深入。

 总结一下这个过程,客户端的协议栈会检查接收到的数据和TCP头部的内容,判断是否有数据丢失,如果没有问题会向服务器返回ACK号。然后协议栈将接收到的数据暂存到接收缓冲区(这个缓冲区是协议栈的)中,然后将数据块按照顺序连接起来还原成原始的数据,最后将数据交还给应用程序,其实是把协议栈缓冲区中的数据复制到浏览器制定的内存地址中,然后浏览器去解析的过程(这个过程还是在read里面实现并把控制流程交还给浏览器的)。

4. 断开连接

 接下来最后一个流程,就是数据发送完成之后的断开连接了,那么断开连接这个操作是由客户端还是服务端发起的呢?
 在协议栈中并没有规定哪一方应该先发起断开操作,通常是由应用程序判断自己的数据已经发起后就可以发起断开动作了。比如我们访问web服务器,发送请求,服务器接受请求处理完成会向客户端返回数据包,等到所有数据都返回了,服务器会主动发起断开操作。下面,我们就以这个例子,服务器先发起断开操作理解这个过程。

 所谓的断开操作也是由发起方调用Socket库的中close()程序实现的,在这个方法中,协议栈会生成包含了断开控制信息的TCP头部,具体来说就是将FIN比特位设置1,然后再委托IP模块将数据发给客户端,接下来,服务器套接字中就会记录下断开操作的相关信息。

 接下来看我们的客户端,在接收到FIN比特位为1的包时,客户端知道了,噢服务器要断开连接了,那好在自己的套接字中标记一下要进入断开操作了,记住这里只是标记一下,同时必须要返回服务器ACK号,告知服务器已收到FIN=1的断开网络包了。

 然后,待到客户端协议栈接收缓冲区数据被应用程序全部取走之后(前面讲到的应用程序的read()操作),客户端感觉时机成熟了,也会向服务器发送一个包含FIN=1头部的网络包,服务器同理也要返回ACK包,至此,双方的通讯正式结束。

在这里插入图片描述

5. 删除套接字

 接下来断开操作的最后一步就是删除套接字,这里尤其注意用来通讯的套接字不会立即删除,而是会等待一段时间后再删除,具体原因如下:

 我们现在举个跟上面相反的断开的例子,由客户端发起断开请求:

  • 客户端发送FIN=1
  • 服务器返回ACK
  • 服务器发送FIN=1
  • 客户端返回ACK

 这里特别注意最后一步,客户端在返回ACK号之后,如果立即删除套接字会发生什么呢?正常情况,可能是服务器收到客户端的ACK号双方通讯结束没问题。但是如果因为网络拥塞问题,服务器没有在规定时间收到第四步的ACK号,那么服务器又发送了一次FIN=1,这里可能会有问题了,因为客户端已经删除了套接字,此时如果恰巧又其他应用程序请求连接服务器并且创建了相同端口号的套接字,那么这个新创建的套接字因为收到了一条莫名奇妙的FIN=1就要进入断开操作了,就会有问题了。所以客户端并不会立即删除套接字,就是为了防止这个问题发生。
 通常,这个等待删除套接字的时间就是几分钟而已。

6. TCP的整体流程

在这里插入图片描述

相关文章:

【网络面试(5)】收发数据及断开服务器(四次挥手)

前面了解到服务器和客户端在创建套接字,建立连接后,就可以进入到下一步,双发可以互相发送和接收数据,本篇博客就来学习一下这个过程。  我们印象里,发送数据应该是我们在浏览器输入网址,敲击回车的一瞬间&…...

【Maven】下载及配置

文章目录 1. 定义2. 下载3. 解压4. 配置环境变量5. 验证6. 特性 1. 定义 Maven 是一个跨平台的项目管理工具。作为 Apache 组织的一个颇为成功的开源项目,其主要服务于基于 Java 平台的项目创建,依赖管理和项目信息管理,是一个自动化构建工具…...

【方法】PPT设置密码后如何修改?

PowerPoint是我们日常和工作中经常用到的办公软件,有时候为了保护文件,还会设置密码,那设置密码后又想要修改密码,怎么操作呢?下面来看看PPT常用的两种密码是如何修改的。 1. “打开密码” 想要修改PPT的“打开密码”…...

第34期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大型语言模型(LLM)等安全领域应用的知识。在这里,您可以…...

2023新版edge浏览器页面加载不出来的解决办法

2023新版edge浏览器页面加载不出来的原因有很多,以下是一些可能的解决方法: - 检查网络连接:确保你的设备连接到稳定的网络,尝试重新启动路由器或调制解调器。 - 清除浏览器缓存:打开edge浏览器,点击右上…...

算法基础之二分与前缀和 day 6

文章目录 二分第一类第二类 前缀和原题链接题目描述输入格式输出格式数据范围输入样例:输出样例: 题目分析示例代码 二分 二分法是我们在高中数学就学习过的一种思想,他也是一种效率较高的查找算法,在编写代码的过程中&#xff0…...

github短视频去除水印项目Douyin_TikTok_Download_API介绍

当下正值短视频盛行的时代。在我们浏览短视频的同时,经常能发现一些精美的图片、引人入胜的文案以及吸引眼球的视频,想要将它们保存到本地。然而,保存下来的图片或视频通常伴随着不太愉悦的水印,这显著降低了使用体验。因此&#…...

FindMy技术用于键盘

键盘是我们生活中不可或缺的输入工具,是人与计算机之间沟通的桥梁,无论是编写文档、浏览网页、玩游戏、或是进行复杂的数据分析,键盘都在其中发挥着关键的作用。此外,键盘还是各种软件的快捷键操作的关键。通过熟练地运用快捷键&a…...

认识jmeter接口测试工具!

jmeter简介 Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。 下载 下载地址:​​​​​​Apache JMeter - Download Apache JMeter 安装 由于Jmeter…...

强大的按钮类CButtonST

转自:哈哈 强大的CButtonST_cbuttonst demo-CSDN博客 这里给大家介绍强大的按钮类CButtonST,可以使您的程序锦上添花。 CButtonST类主要包括BtnST.h、BtnST.cpp、BCMenu.h和BCMenu.cpp四个文件。先将上述4个文件复制到自己的工程,然后在VC开…...

学习ing

记录 1.光圈的大小由一个称为“F值”的数字表示,这个数字越小,光圈就越大,光线也就越多。一般来说,使用较小的F值可以拍摄出更亮的照片,而使用较大的F值可以拍摄出更暗的照片。 2.光圈可以控制相机的曝光时间&#x…...

linux下数据库定时备份

1.编写shell脚本 #!/bin/bash USER"root" PASSWORD"Root.36#336" DATABASE"backup_test" HOSTNAME"127.0.0.1" DATEdate %Y%m%d_%H%M%S #日期格式(作为文件名) BACKUP_DIR/home/mysql/DB_backup/ #备份文件存…...

Qt/QML编程学习之心得:QSocketNotifier(二十一)

QSocketNotifier在Qt中怎么使用? QSocketNotifier使Qt的事件循环与其他基于文件描述符的事件循环集成成为可能。在Qt的主事件循环(QCoreApplication::exec())中检测到文件描述符操作。 使用低级(通常是特定于平台的)API打开设备后,可以创建一个套接字通知程序来监视文…...

【linux】lsblk和df -h显示的磁盘信息不同

【问题分析】 lsblk 查看的是block device,也就是逻辑磁盘大小。 df查看的是file system, 也就是文件系统层的磁盘大小。 这种情况应该是block device容量变大,单还没有反映到file system中。 【问题解决】 如果是ext{2,3,4}文件系统的话,可以用res…...

如何开发属于自己的小程序?

随着移动互联网的快速发展,小程序已成为一种不可忽视的力量。对于许多企业和个人而言,拥有一个属于自己的小程序不仅能提高品牌曝光度,还能带来实实在在的收益。那么,如何开发属于自己的小程序呢?本文将为你揭秘这一过…...

湖仓架构的演进

1.数据仓库架构的历史演进 起初,业界数据处理首选方式是数仓架构。通常数据处理的流程是把一些业务数据库,通过ETL的方式加载到Data Warehouse中,再在前端接入一些报表或者BI的工具去展示。 数据仓库概念是 Inmon 于 1990 年提出并给出了完…...

【头歌实训】Spark MLlib ( Python 版 )

文章目录 第1关:基本统计编程要求测试说明答案代码 第2关:回归编程要求测试说明参考资料答案代码 第3关:分类编程要求测试说明参考资料答案代码 第4关:协同过滤编程要求测试说明参考资料答案代码 第5关:聚类编程要求测…...

Java基础进阶(学习笔记)

注:本篇的代码和PPT图片来源于黑马程序员,本篇仅为学习笔记 static static 是静态的意思,可以修饰成员变量,也可以修饰成员方法 修饰成员的特点: 被其修饰的成员, 被该类的所有对象所共享 多了一种调用方式, 可以通过…...

uView NoticeBar 滚动通知

该组件用于滚动通告场景&#xff0c;有多种模式可供选择 #平台差异说明 App&#xff08;vue&#xff09;App&#xff08;nvue&#xff09;H5小程序√√√√ #基本使用 通过text参数设置需要滚动的内容 <template><view><u-notice-bar :text"text1&quo…...

外包干了3个多月,技术退步明显。。。。。

先说一下自己的情况&#xff0c;本科生生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…...

JSON的一些资源

以下是一些推荐的学习资源&#xff1a; 1. **官方网站**: - JSON.org: 这是一个很好的起点&#xff0c;它提供了JSON的基本介绍和语法规则。 2. **在线教程和课程**: - CSDN全方面学习各种资源。 - W3Schools (w3schools.com): 提供了一个关于JSON的教程&#xff0c;涵…...

最优化理论期末复习笔记 Part 1

数学基础线性代数 从行的角度从列的角度行列式的几何解释向量范数和矩阵范数 向量范数矩阵范数的更强的性质的意义 几种向量范数诱导的矩阵范数 1 范数诱导的矩阵范数无穷范数诱导的矩阵范数2 范数诱导的矩阵范数 各种范数之间的等价性向量与矩阵序列的收敛性 函数的可微性与展…...

鸿蒙应用中的通知

目录 1、通知流程 2、发布通知 2.1、发布基础类型通知 2.1.1、接口说明 2.1.2、普通文本类型通知 2.1.3、长文本类型通知 2.1.4、多行文本类型通知 2.1.5、图片类型通知 2.2、发布进度条类型通知 2.2.1、接口说明 2.2.2、示例 2.3、为通知添加行为意图 2.3.1、接…...

如何停止一个运行中的Docker容器

要停止一个运行中的Docker容器&#xff0c;你可以使用以下命令&#xff1a; docker stop <容器ID或容器名> 将 <容器ID或容器名> 替换为你要停止的具体容器的标识符或名称。你可以使用以下命令查看正在运行的容器&#xff1a;docker ps 这将列出所有正在运行的…...

Linux第19步_安装“Ubutun交叉编译工具链”

由于Ubuntu系统使用的GCC编译器&#xff0c;编译结果是X86文件&#xff0c;只能在X86上运行&#xff0c;不能在ARM上直接运行。因此&#xff0c;还要安装一个“Ubutun交叉编译工具链”&#xff0c;才可以在ARM上运行。 arm-none-linux-gnueabi-gcc是 Codesourcery 公司&#x…...

【论文阅读笔记】 Representation Learning with Contrastive Predictive Coding

Representation Learning with Contrastive Predictive Coding 摘要 这段文字是论文的摘要&#xff0c;作者讨论了监督学习在许多应用中取得的巨大进展&#xff0c;然而无监督学习并没有得到如此广泛的应用&#xff0c;仍然是人工智能中一个重要且具有挑战性的任务。在这项工作…...

CNN——LeNet

1.LeNet概述 LeNet是Yann LeCun于1988年提出的用于手写体数字识别的网络结构&#xff0c;它是最早发布的卷积神经网络之一&#xff0c;可以说LeNet是深度CNN网络的基石。 当时&#xff0c;LeNet取得了与支持向量机&#xff08;support vector machines&#xff09;性能相…...

分类模型评估方法

1.数据集划分 1.1 为什么要划分数据集? 思考&#xff1a;我们有以下场景&#xff1a; 将所有的数据都作为训练数据&#xff0c;训练出一个模型直接上线预测 每当得到一个新的数据&#xff0c;则计算新数据到训练数据的距离&#xff0c;预测得到新数据的类别 存在问题&…...

RabbitMQ高级

文章目录 一.消息可靠性1.生产者消息确认 MQ的一些常见问题 1.消息可靠性问题:如何确保发送的消息至少被消费一次 2.延迟消息问题:如何实现消息的延迟投递 3.高可用问题:如何避免单点的MQ故障而导致的不可用问题 4.消息堆积问题:如何解决数百万消息堆积&#xff0c;无法及时…...

SonarQube 漏洞扫描

SonarQube 漏洞扫描 一、部署服务 1.1 docker方式部署 #安装docker curl -L download.beyourself.org.cn/shell-project/os/get-docker-latest.sh | sh yum install -y docker-compose #进去输入:set paste可以保证不穿行 [rootlocalhost sonar]# vim docker-compose.yml v…...

网站设计排行榜前十/品牌营销策划培训课程

SpringBoot超大文件上传&#xff0c;秒传&#xff01;分片上传!断电续传&#xff01;&#xff08;总结&#xff09;一. 秒传1、什么是秒传2、本文实现的秒传核心逻辑二. 分片上传1、什么是分片上传2、分片上传的场景三. 断点续传1、什么是断点续传2、应用场景3、实现断点续传的…...

linux下载wordpress/保定网站seo

姓名年龄性别职位死亡时间所在行业死亡原因注信息来源王江民59岁男酷6网研发部 软件工程师2010.4.4IT心脏病死亡时仅 入职3个月百度百科罗耀明80后男江民创始人 兼总裁2009.11.0IT急性病毒 性心肌炎加班 彭小琦30岁左右男搜狐无线事业部 技术人员2010.4.0IT过度劳累 导致猝死工…...

山东做网站建设的好公司哪家好/真正免费建站

有时候,通过查看在线重做日志 redo log 每小时的切换次数,可以查看故障发生的时间点! SQL 语句如下: set linesize 260 pagesize 1000; col h0 for 999 col h1 for 999; col h2 for 999; col h3 for 999; col h4 for 999; col h5 for 999...

赣州章贡区人口/西安网站关键词优化推荐

.├── app.js├── bin│ └── www├── node_modules│ ├── body-parser│ ├── cookie-parser│ ├── debug│ ├── express│ ├── jade│ ├── morgan│ └── serve-favicon├── package.json├── public│ ├── images│ …...

wordpress安卓ios应用/seo店铺描述例子

“笑来老师的课讲得好&#xff0c;但是如果听完课还买笑来老师的币&#xff0c;那说明你没学到家。”一名资深韭菜评价道。文 | 昕楠 运营 | 盖遥出品 | Odaily星球日报&#xff08;ID&#xff1a;o-daily&#xff09;牛市让不少退圈大佬“回归”。李笑来便是其一。一年前的 7…...

网站必须做百度推广才能被别人搜到吗/网店推广方式

C# asp.net SQL存储过程写法Insert 插入语句&#xff0c;及其在asp.net中的调用方法 1、SQL存储过程语句&#xff1a; 向SQL里插入一条记录&#xff1a; CREATE PROCEDURE dbo.Ta_testnames nchar(255),sex nchar(255) ASinsert into T_a (names,sex)values (names,sex)GO 2、S…...