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

news2024/11/26 2:29:46

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

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的整体流程

在这里插入图片描述

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

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

相关文章

RocketMQ 生产者源码分析:DefaultMQProducer、DefaultMQProducerImpl

🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者 📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代 🌲文章所在专栏&…

(九)上市企业实施IPD成功案例分享之——欧普

LED通用照明应用是LED照明应用市场的第一驱动力,由于LED照明技术发展迅速,以及成本快速下降,已成为全球主流照明光源。近年来,通过将智能控制模块嵌入LED通用照明终端,形成了具有自动控制、系统化控制等功能的智能照明…

Java8 Lambda 表达式

文章目录 🍉 Java 8 介绍🍉 Lambda 表达式🍅🍅 基础语法🍅🍅 案例 🍉 函数式接口🍅🍅 内置的四大核心函数式接口🍅🍅 案例 🍉 Java 8 …

linux驱动(一):led

本文主要探讨210的led驱动相关知识。 驱动 操作系统驱动硬件的代码,驱动上层是系统调用API,下层是硬件 宏内核:内核整体上为一个过程实现,运行在同一地址空间,相互调用简单高效 微内核:功能为独立过程,过程间通过IPC通信 …

国科大图像处理2023速通期末——汇总2017-2019

国科大2023.12.28图像处理0854期末重点 图像处理 王伟强 作业 课件 资料 一、填空 一个阴极射线管它的输入与输出满足 s r 2 sr^{2} sr2,这将使得显示系统产生比希望的效果更暗的图像,此时伽马校正通常在信号进入显示器前被进行预处理,令p…

上海亚商投顾:三大指数红盘收官!沪指今年累计跌3.7%

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 A股12月29日迎来2023年收官之战,三大股指延续反弹走势,最终集体红盘报收。纵观全年&am…

CMake入门教程【基础篇】CMake+vs2022+nmake构建项目

文章目录 1.vs编译器下载安装2.运行nmake测试3.CMake下载安装4.运行CMake测试5.使用CMakeNMake构建项目代码目录代码实现 6.运行项目 1.vs编译器下载安装 下载地址 :https://visualstudio.microsoft.com/zh-hans/vs/ 点击截图处下载 勾选红框的内容即可 安装 2.运行nmak…

echarts手动触发气泡的显示和隐藏

点击echarts图表后将点击的那个进行突出显示 <template><div id"demo"> </div><el-button type"primary" click"set">设置</el-button><el-button type"primary" click"cancel">取消&…

数据结构与算法教程,数据结构C语言版教程!(第二部分、线性表详解:数据结构线性表10分钟入门)四

第二部分、线性表详解&#xff1a;数据结构线性表10分钟入门 线性表&#xff0c;数据结构中最简单的一种存储结构&#xff0c;专门用于存储逻辑关系为"一对一"的数据。 线性表&#xff0c;基于数据在实际物理空间中的存储状态&#xff0c;又可细分为顺序表&#xff…

嵌入式视频播放器(mplayer)

1.文件准备&#xff1a; MPlayer-1.0rc2.tar.bz2 libmad-0.15.1b.tar.gz 直接Git到本地 git clone https://gitee.com/zxz_FINE/mplayer_tarball.git 2.文件夹准备&#xff1a; src存放解压后的源码文件&#xff0c;target_Mplayer存放编译安装的目标文件 mkdir src targe…

自动驾驶论文

文章目录 一、Convolutional Social Pooling for Vehicle Trajectory Prediction二、QCNet&#xff1a;Query-Centric Trajectory Prediction三、VectorNet: Encoding HD Maps and Agent Dynamics from Vectorized Representation 一、Convolutional Social Pooling for Vehicl…

Ts自封装WebSocket心跳重连

WebSocket是一种在单个TCP连接上进行全双工通信的协议&#xff0c;允许客户端和服务器之间进行双向实时通信。 所谓心跳机制&#xff0c;就是在长时间不使用WebSocket连接的情况下&#xff0c;通过服务器与客户端之间按照一定时间间隔进行少量数据的通信来达到确认连接稳定的手…

【快速全面掌握 WAMPServer】12.WAMPServer 故障排除经验大总结

网管小贾 / sysadm.cc 众所周知&#xff0c;搞开发需要先搭建相应的编程和调试环境。 对于 PHPer 来说&#xff0c;很多像我一样的新手小白们入门的时候&#xff0c;通常会选择一些集成开发环境包&#xff0c;其中就有 WampServer 。 集成环境包被许多人所诟病&#xff0c;说…

防火墙-访问控制、安全审计、网络设备防护检查表

防火墙标准检查表 项目管理、开发全文档获取&#xff1a;软件项目开发全套文档下载_软件项目技术实现文档-CSDN博客 1、访问控制类检查 2、安全审计类检查 3、网络设备防护类检查 防火墙标准检查表 分类 测评项 预期结果 访问控制 应在网络边界部署访问控制设备&#xf…

QT的信号与槽

QT的信号与槽 文章目录 QT的信号与槽前言一、QT 打印"hello QT"的dome二、信号和槽机制&#xff1f;二、信号与槽的用法1、QT5的方式1. 无参的信号与槽的dome2.带参的信号与槽dome 2、QT4的方式3、C11的语法 Lambda表达式1、函数对象参数2、操作符重载函数参数3、可修…

爬虫实战-微博评论爬取

简介 最近在做NLP方面的研究&#xff0c;以前一直在做CV方面。最近由于chatgpt&#xff0c;所以对NLP就非常感兴趣。索性就开始研究起来了。 其实我们都知道&#xff0c;无论是CV方向还是NLP方向的模型实现&#xff0c;都是离不开数据的。哪怕是再先进的代码&#xff0c;都是…

红队攻防实战之DC2

吾愿效法古圣先贤&#xff0c;使成千上万的巧儿都能在21世纪的中华盛世里&#xff0c;丰衣足食&#xff0c;怡然自得 0x01 信息收集: 1.1 端口探测 使用nmap工具 可以发现开放了80端口&#xff0c;网页服务器但是可以看出做了域名解析&#xff0c;所以需要在本地完成本地域名…

车载毫米波雷达及芯片新趋势研究3--自动驾驶、国产替代与外延场景需求快速增长打开市场空间

3.1 多传感器融合路线优势将不断扩大&#xff0c;引发更多毫米波雷达及芯片需求  纯视觉自动驾驶路线是通过以光学摄像头为传感器结合大量算法训练以模拟人类视觉驾驶为逻辑的自动驾驶方案。 纯视觉方案“轻硬件、重软件”&#xff0c;由其采用的摄像头成本较低&#xff0c;…

大数据Doris(四十五):物化视图选择最优

文章目录 物化视图选择最优 物化视图选择最优 下面详细解释一下第一步最优物化视图是被如何选择出来的。 这里分为两个步骤: 对候选集合进行一个过滤。只要是查询的结果能从物化视图数据计算(取部分行,部分列,或部分行列的聚合)出都可以留在候选集中,过滤完成后候选集合…

vmware安装openEuler 22.03 LTS操作系统

vmware安装openEuler 22.03 LTS操作系统 1、下载openEuler操作系统镜像文件2、安装openEuler操作系统3、配置openEuler操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载openEuler操作系统镜像文件 官网下载链接 链接: https://www.openeuler.or…