计算机网络01

文章目录

    • 浏览器输入URL后发生了什么?
    • Linux 系统是如何收发网络包的?
      • Linux 网络协议栈
      • Linux 接收网络包的流程
      • Linux 发送网络包的流程

浏览器输入URL后发生了什么?

  • URL解析
    • 当在浏览器中输入URL后,浏览器首先对拿到的URL进行识别,抽取出域名字段。
  • DNS查询
    • 1.查询浏览器缓存(浏览器会缓存之前拿到的DNS 2-30分钟时间),如果没有找到,那么->
    • 2.检查系统缓存,检査hosts文件,这个文件保存了一些以前访问过的网站的域名和IP的数据。它就像是一个本地的数据库。如果找到就可以直接获取目标主机的IP地址了。没有找到的话,那么->
    • 3.检查路由器缓存,路由器有自己的DNS缓存,可能就包括了这在査询的内容;如果没有,那么->
    • 4.查询ISP DNS 缓存: ISP服务商DNS缓存(本地服务器缓存)那里可能有相关的内容,如果还不行的话,那么->
    • 5.递归查询:从根域名服务器到顶级域名服务器再到权威域名服务器依次搜索对应目标域名的IP.
      • 通过以上的查找,就可以获取到域名对应的IP了。接下来就是向该IP地址定位的HTTP服务器发起TCP连接。
  • TCP连接
    • 三次握手,四次挥手
  • 请求和传输数据
    • 发起HTTP请求:建立TCP连接后,浏览器会向服务器发送HTTP请求。这个请求包括请求方法(如GET、POST)、请求头(包含一些额外的信息,如用户代理、Cookie等)以及可能的请求体(对于POST请求)。
    • 服务器处理请求:服务器接收到浏览器发送的请求后,根据请求的路径和其他信息,处理请求并生成响应。
    • 接收响应:浏览器接收到服务器发送的响应,响应包括状态码(表示请求成功、失败或其他状态)、响应头(包含一些元数据,如内容类型、缓存控制等)和响应体(实际的响应数据)。
    • 渲染页面:如果响应的内容是HTML,浏览器会解析HTML、构建DOM树和CSSOM树,然后将它们合并为渲染树,最终绘制到屏幕上。
  • 关闭连接:页面渲染完成后,浏览器会关闭与服务器的TCP连接,释放资源。

Linux 系统是如何收发网络包的?

Linux 网络协议栈

Linux 网络协议栈的样子,其实就类似于 TCP/IP 的四层结构:  

image.png

Linux 接收网络包的流程

网卡是计算机里的一个硬件,专门负责接收和发送网络包,当网卡接收到一个网络包后,会通过 DMA 技术,将网络包写入到指定的内存地址,也就是写入到 Ring Buffer ,这个是一个环形缓冲区,接着就会告诉操作系统这个网络包已经到达。
那应该怎么告诉操作系统这个网络包已经到达了呢?
最简单的一种方式就是触发中断,也就是每当网卡收到一个网络包,就触发一个中断告诉操作系统。
但是,这存在一个问题,在高性能网络场景下,网络包的数量会非常多,那么就会触发非常多的中断,要知道当 CPU 收到了中断,就会停下手里的事情,而去处理这些网络包,处理完毕后,才会回去继续其他事情,那么频繁地触发中断,则会导致 CPU 一直没完没了的处理中断,而导致其他任务可能无法继续前进,从而影响系统的整体效率。
所以为了解决频繁中断带来的性能开销,Linux 内核在 2.6 版本中引入了 NAPI 机制,它是混合「中断和轮询」的方式来接收网络包,它的核心概念就是不采用中断的方式读取数据,而是首先采用中断唤醒数据接收的服务程序,然后 poll 的方法来轮询数据。
因此,当有网络包到达时,会通过 DMA 技术,将网络包写入到指定的内存地址,接着网卡向 CPU 发起硬件中断,当 CPU 收到硬件中断请求后,根据中断表,调用已经注册的中断处理函数。
硬件中断处理函数会做如下的事情:

  • 需要先**「暂时屏蔽中断」**,表示已经知道内存中有数据了,告诉网卡下次再收到数据包直接写内存就可以了,不要再通知 CPU 了,这样可以提高效率,避免 CPU 不停的被中断。
  • 接着,发起**「软中断」**,然后恢复刚才屏蔽的中断。

至此,硬件中断处理函数的工作就已经完成。
硬件中断处理函数做的事情很少,主要耗时的工作都交给软中断处理函数了。
:::info
软中断的处理
:::
内核中的 ksoftirqd 线程专门负责软中断的处理,当 ksoftirqd 内核线程收到软中断后,就会来轮询处理数据。
ksoftirqd 线程会从** Ring Buffer** 中获取一个数据帧,用 sk_buff 表示,从而可以作为一个网络包交给网络协议栈进行逐层处理。
:::info
网络协议栈
:::
首先,会先进入到网络接口层,在这一层会检查报文的合法性,如果不合法则丢弃,合法则会找出该网络包的上层协议的类型,比如是 IPv4,还是 IPv6,接着再去掉帧头和帧尾,然后交给网络层。
到了网络层,则取出 IP 包,判断网络包下一步的走向,比如是交给上层处理还是转发出去。当确认这个网络包要发送给本机后,就会从 IP 头里看看上一层协议的类型是 TCP 还是 UDP,接着去掉 IP 头,然后交给传输层。
传输层取出 TCP 头或 UDP 头,根据四元组「源 IP、源端口、目的 IP、目的端口」 作为标识,找出对应的 Socket,并把数据放到 Socket 的接收缓冲区。
最后,应用层程序调用 Socket 接口,将内核的 Socket 接收缓冲区的数据「拷贝」到应用层的缓冲区,然后唤醒用户进程。
至此,一个网络包的接收过程就已经结束了,你也可以从下图左边部分看到网络包接收的流程,右边部分刚好反过来,它是网络包发送的流程。
image.png

Linux 发送网络包的流程

如上图的右半部分,发送网络包的流程正好和接收流程相反。
首先,应用程序会调用 Socket 发送数据包的接口,由于这个是系统调用,所以会从用户态陷入到内核态中的 Socket 层,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区
接下来,网络协议栈从 Socket 发送缓冲区中取出 sk_buff,并按照 TCP/IP 协议栈从上到下逐层处理。
如果使用的是 TCP 传输协议发送数据,那么先拷贝一个新的 sk_buff 副本 ,这是因为 sk_buff 后续在调用网络层,最后到达网卡发送完成的时候,这个 sk_buff 会被释放掉。而** TCP 协议是支持丢失重传的,在收到对方的 ACK 之前,这个 sk_buff 不能被删除。所以内核的做法就是每次调用网卡发送的时候,实际上传递出去的是 sk_buff 的一个拷贝,等收到 ACK 再真正删除。**
接着,对 sk_buff 填充 TCP 头。这里提一下,sk_buff 可以表示各个层的数据包,在应用层数据包叫 data,在 TCP 层我们称为 segment,在 IP 层我们叫 packet,在数据链路层称为 frame。
你可能会好奇,为什么全部数据包只用一个结构体来描述呢?协议栈采用的是分层结构,上层向下层传递数据时需要增加包头,下层向上层数据时又需要去掉包头,如果每一层都用一个结构体,那在层之间传递数据的时候,就要发生多次拷贝,这将大大降低 CPU 效率。
于是,为了在层级之间传递数据时,不发生拷贝,只用 sk_buff 一个结构体来描述所有的网络包,那它是如何做到的呢?是通过调整 sk_buff 中 data 的指针,比如:

  • 当接收报文时,从网卡驱动开始,通过协议栈层层往上传送数据报,通过增加 skb->data 的值,来逐步剥离协议首部。
  • 当要发送报文时,创建 sk_buff 结构体,数据缓存区的头部预留足够的空间,用来填充各层首部,在经过各下层协议时,通过减少 skb->data 的值来增加协议首部。

你可以从下面这张图看到,当发送报文时,data 指针的移动过程。
image.png
至此,传输层的工作也就都完成了。
然后交给网络层,在网络层里会做这些工作:选取路由(确认下一跳的 IP)、填充 IP 头、netfilter 过滤、对超过 MTU 大小的数据包进行分片。处理完这些工作后会交给网络接口层处理。
网络接口层会通过** ARP 协议获得下一跳的 MAC 地址**,然后对 sk_buff 填充帧头和帧尾,接着将 sk_buff 放到网卡的发送队列中。
这一些工作准备好后**,会触发「软中断」告诉网卡驱动程序,这里有新的网络包需要发送**,驱动程序会从发送队列中读取 sk_buff,将这个 sk_buff 挂到 RingBuffer 中,接着将 sk_buff 数据(RingBuffer)映射到网卡可访问的内存 DMA 区域,最后触发真实的发送。
当数据发送完成以后,其实工作并没有结束,因为内存还没有清理。当发送完成的时候,网卡设备会触发一个硬中断来释放内存,主要是释放 sk_buff 内存和清理 RingBuffer 内存。
最后,当收到这个 TCP 报文的 ACK 应答时,传输层就会释放原始的 sk_buff 。
发送网络数据的时候,涉及几次内存拷贝操作?
第一次,调用发送数据的系统调用的时候,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区。
第二次,在使用 TCP 传输协议的情况下,从传输层进入网络层的时候,每一个 sk_buff 都会被克隆一个新的副本出来。副本 sk_buff 会被送往网络层,等它发送完的时候就会释放掉,然后原始的 sk_buff 还保留在传输层,目的是为了实现 TCP 的可靠传输,等收到这个数据包的 ACK 时,才会释放原始的 sk_buff 。
第三次,当 IP 层发现 sk_buff 大于 MTU 时才需要进行。会再申请额外的 sk_buff,并将原来的 sk_buff 拷贝为多个小的 sk_buff。

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

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

相关文章

2024最全RabbitMQ集群方案汇总

之前在网上找rabbitmq集群方案有哪几种时,基本上看到的答案都不太一样,所以此文的主要目的是梳理一下rabbitmq集群方案,对rabbitmq集群方案的笔记并不是搭建的笔记。 总结了一些文章,rabbitmq集群大概有五种方案:普通…

[Linux安全运维] iptables包过滤

前言 防火墙是网络安全中非常重要的设备,是一种将内部网络和外部网络隔离开的技术。简单来说,防火墙技术就是访问控制技术,由规则和动作组成。 1. Linux 包过滤防火墙 1 .1 概述 iptables: 指的是管理Linux防火墙的命令程序&a…

Windows 下后台启动 jar 包,UTF-8 启动 jar 包_windows启动jar

转自:https://blog.csdn.net/2401_83817971/article/details/137514739 本文介绍了如何使用javaw.exe后台启动Javajar包,如何在Windows中管理和设置cmd编码,以及与Python开发相关的学习资源。包括UTF-8编码启动jar包的方法和Windows下关闭后台服务的技…

superset 不显示mysql的选项问题

superset不显示mysql的选项 数据库驱动未安装:确保你已经安装了Python的MySQL数据库驱动,比如mysqlclient。 pip install mysqlclient

vue一些npm i 时报错问题解决【JAVA前后端分离】

前端vue npm i 安装时出现 作为一个懂些前端得 JAVA开发自然是要粗暴解决这个问题了 问题解决 使用命令 npx -p npm6 npm i 即可编译 原因: ERESOLVE与npm版本有关,因为npm版本高对某些事情比npm6.x更严格。通常,最简单的解决方法是将--…

【机器学习基础】机器学习概述与实践基础

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科,通过算法和模型让计算机从数据中学习,进行模型训练和优化,做出预测、分类和决策支持。Python成为机器学习的首选语言,…

STC12C5A60S2单片机输出pwm的方法

所谓的pwm输出就是让单片机在某个管脚上按照时间输出特定频率和占空比的矩形方波。这里面有两个参数,一是频率,二是占空比。两者互不干涉。以STC12C5A60S2为例子,本51型单片机可以有两路pwm输出。以其中的一路为例说明; 首先说频…

Teltonika FMXXX系列定位器解析说明

1.产品外观 2.数据包说明 2.1.登录包 **模块第一次上线,先发送其对应的IMEI号,数据包如下:** 000F313233343536373839303132333435**数据包解析如下:** 000F --packet starts 313233343536373839303132333435 --IMEI 1234567890…

区块链软硬件协同,做产业数字化转型的“安全官” |《超话区块链》直播预告

今年的两会政府工作报告提出:“产业的数字化(行业数字化转型)是发展新质生产力的核心,是推动产业升级实现高质量发展的关键。”全面推进产业数字化,需要技术创新与产业应用深入协同;立足可持续发展的长远目…

泰迪智能科技入选广东省2024年第三批职业技能等级认定社会培训评价组织名单

7月17日,根据《关于公布广东省2023年社会培训评价组织新申请机构进入培育辅导期名单的通知》(粤人社函〔2023〕269号)、《关于公布广东省2023年社会培训评价组织(“产教评”链主培育单位)进入培育辅导期名单的通知》&a…

网络安全是什么?怎么入门网络安全?

一、网络安全的定义 网络安全,简单来说,就是保护网络系统中的硬件、软件以及其中的数据不因偶然或恶意的原因而遭到破坏、更改、泄露,保障系统连续可靠正常地运行,网络服务不中断。 随着信息技术的飞速发展,网络安全的…

docker compose 安装 kafka

一 前置准备 创建 /data/kafkadata /data/zookeeper-1用于保存kafka和zookeeper的配置文件 kafkadata中创建三个文件夹 /kafka1 /kafka2 /kafka3,用于存放三个kafka节点的配置文件 zookeeper-1文件夹中创建 /conf /data /logs /datalog四个文件夹,用于…

IoTDB 入门教程 实战篇④——C#示例(开源)

文章目录 一、前文二、新建C#项目三、NuGet安装四、示例源码五、查询数据六、参考 一、前文 IoTDB入门教程——导读 本文详细阐述了如何通过一个C#项目成功连接到IoTDB时序数据库,进而展示了如何向该数据库高效地写入数据以及执行精确的数据查询操作。 此示例旨在为…

Redis高可用之持久化,以及reids的性能管理

一、redis高可用: 在集群当中有一个非常重要的指标,提供正常服务的时间的百分比(365天)99.9% redis的高可用含义更加宽泛,正常服务是指标之一,数据容量的扩展,数据的安全性 在redis中实现高可…

多模态大模型(MM-LLMs)近期概述

《MM-LLMs: Recent Advances in MultiModal Large Language Models》 论文地址:https://arxiv.org/abs/2401.13601 GitHub地址:https://mm-llms.github.io/ 1.介绍 目的:MM-LLMs旨在减少计算费用并提高多模态预训练的效率, 因为从头开始训…

Data Augmentation数据增强

目录 数据增强是什么 为什么数据增强 数组增强分类 有监督数据增强 无监督数据增强 数据增强是什么 数据增强又称数据扩增,是一种通过应用合理且随机的变换(例如图像位移、旋转)来增加训练集多样性的技术。让有限的数据产生等价于更多数…

Jenkins集成JDK、git、gitee、maven逐步实现自动拉取,自动部署,自动启动

1. jenkins集成JDK 成功登录Jenkins后,选择Manage Jenkins,选择Tools 集成JDK 2. jenkins集成git 因为Jenkins自动从git远程仓库拉取代码 首先要在Jenkins所在的linux服务器上安装git yum install -y git然后,实行集成JDK的第一步 配置g…

C#:枚举及位标志周边知识详解(小白入门)

文章目录 枚举为什么要有枚举?枚举的性质设置默认类型和显式设置成员的值 位标志(重要)位标记是什么及作用位标志周边知识HasFlag判断是否有该功能枚举前面加Flags的好处 关于枚举的更多知识using static简化代码获取枚举成员的字面量 枚举 为什么要有枚举? 为了增加代码的…

FlowUs息流作为一款技术驱动的笔记和知识管理平台,其核心功能和技术优势为新媒体行业带来了革命性的工作效率提升

FlowUs息流作为一款技术驱动的笔记和知识管理平台,其核心功能和技术优势为新媒体行业带来了革命性的工作效率提升。以下是对其技术特色的深入解析: 本地化技术优化:FlowUs息流通过深入研究中文用户的操作习惯,实现了界面的本地化设…

【WRF安装第二期(Ubuntu)】搭建WRF编译所需系统-系统环境检验

WRF安装第二期:搭建WRF编译所需系统-系统环境检验 0 升级和安装基础环境1 系统环境检验(System Environment Tests)1.1 检验和安装基础包1.1.1 安装指令1.1.2 检验指令 1.2 WRF安装的目录结构1.2.1 WRF系统环境测试 1.3 测试编译器&#xff0…