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

网络协议二

一、套接字Socket

基于 TCP UDP 协议的 Socket 编程,在讲 TCP 和 UDP 协议的时候,我们分客户端和服务端,在写程序的时候,我们也同样这样分。
在网络层,Socket 函数需要指定到底是 IPv4 还是 IPv6,分别对应设置为 AF_INET 和 AF_INET6。另外,还要指定到底是 TCP 还是 UDP。还记得咱们前面讲过的,TCP 协议是基于数据流的,所以设置为 SOCK_STREAM,而 UDP 是基于数据报的,因而设置为 SOCK_DGRAM。

监听的 Socket 和真正用来传数据的 Socket 是两个,一个叫作监听 Socket,一个叫作已连接 Socket

比喻:接待客人

想象你在家里准备接待客人,你有一个门铃和一个客厅。门铃相当于监听 Socket,而客厅相当于已连接 Socket。

  1. 监听 Socket(门铃)

    • 你家的门铃一直在等待有人按下它,这就像服务器上的监听 Socket 一直在等待新的连接请求。
    • 当有人按下门铃时,你知道有客人到访了,但你还不知道是谁,也还没有开始与客人交谈。
  2. 已连接 Socket(客厅)

    • 当你开门迎接客人,并带他们到客厅后,你就开始与客人交流了,这时候的客人就相当于已连接 Socket。
    • 在客厅里,你可以与每个客人进行独立的对话,不会相互干扰。

技术解释

在网络编程中,特别是 TCP 服务器程序中,监听 Socket 和已连接 Socket 是两个不同的概念和用途:

  1. 监听 Socket

    • 作用:用来监听和接受新的连接请求。
    • 创建:在服务器启动时创建,并绑定到特定的 IP 地址和端口。
    • 工作方式:服务器调用 listen() 方法,使这个 Socket 进入监听状态,等待客户端的连接请求。当有客户端请求连接时,服务器调用 accept() 方法,从监听 Socket 接受连接请求。
  2. 已连接 Socket

    • 作用:用来与客户端进行实际的数据传输。
    • 创建:当服务器调用 accept() 方法并成功接收一个客户端连接后,会生成一个新的已连接 Socket。这个 Socket 专门用于与该客户端进行通信。
    • 工作方式:服务器使用这个已连接 Socket 调用 send()recv() 方法,与客户端交换数据。

基于 TCP 协议的 Socket 程序函数调用过程

在这里插入图片描述

write() 和 read():适用于所有类型的文件描述符,包括 Socket,功能简单直接。
send() 和 recv():专为网络 Socket 设计,提供额外的功能和灵活性,通过 flags 参数控制行为。

基于 UDP 协议的 Socket 程序函数调用过程

对于 UDP 来讲,过程有些不一样。UDP 是没有连接的,所以不需要三次握手,也就不需要调用 listen 和 connect,但是,UDP 的的交互仍然需要 IP 和端口号,因而也需要 bind。UDP 是没有维护连接状态的,因而不需要每对连接建立一组 Socket,而是只要有一个 Socket,就能够和多个客户端通信。也正是因为没有连接状态,每次通信的时候,都调用 sendto 和 recvfrom,都可以传入 IP 地址和端口。
在这里插入图片描述

服务器如何接更多的项目?

会了这几个基本的 Socket 函数之后,你就可以轻松地写一个网络交互的程序了。就像上面的过程一样,在建立连接后,进行一个 while 循环。客户端发了收,服务端收了发。
当然这只是万里长征的第一步,因为如果使用这种方法,基本上只能一对一沟通。如果你是一个服务器,同时只能服务一个客户,肯定是不行的。这就相当于老板成立一个公司,只有自己一个人,自己亲自上来服务客户,只能干完了一家再干下一家,这样赚不来多少钱。
那作为老板你就要想了,我最多能接多少项目呢?当然是越多越好。
我们先来算一下理论值,也就是最大连接数,系统会用一个四元组来标识一个 TCP 连接。
{本机 IP, 本机端口, 对端 IP, 对端端口}
服务器通常固定在某个本地端口上监听,等待客户端的连接请求。因此,服务端端 TCP 连接四元组中只有对端 IP, 也就是客户端的 IP 和对端的端口,也即客户端的端口是可变的,因此,最大 TCP 连接数 = 客户端 IP 数×客户端端口数。对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。
当然,服务端最大并发 TCP 连接数远不能达到理论上限。首先主要是文件描述符限制,按照上面的原理,Socket 都是文件,所以首先要通过 ulimit 配置文件描述符的数目;另一个限制是内存,按上面的数据结构,每个 TCP 连接都要占用一定内存,操作系统是有限的。

所以,作为老板,在资源有限的情况下,要想接更多的项目,就需要降低每个项目消耗的资源数目。

方式一:将项目外包给其他公司(多进程方式)

方式二:将项目转包给独立的项目组(多线程方式)

上面这种方式你应该也能发现问题,如果每次接一个项目,都申请一个新公司,然后干完了,就注销掉这个公司,实在是太麻烦了。毕竟一个新公司要有新公司的资产,有新的办公家具,每次都买了再卖,不划算。
于是你应该想到了,我们可以使用线程。相比于进程来讲,这样要轻量级的多。如果创建进程相当于成立新公司,购买新办公家具,而创建线程,就相当于在同一个公司成立项目组。一个项目做完了,那这个项目组就可以解散,组成另外的项目组,办公家具可以共用。

上面基于进程或者线程模型的,其实还是有问题的。新到来一个 TCP 连接,就需要分配一个进程或者线程。一台机器无法创建很多进程或者线程。有个C10K,它的意思是一台机器要维护 1 万个连接,就要创建 1 万个进程或者线程,那么操作系统是无法承受的。如果维持 1 亿用户在线需要 10 万台服务器,成本也太高了。

方式三:一个项目组支撑多个项目(IO 多路复用,一个线程维护多个 Socket)

当然,一个项目组可以看多个项目了。这个时候,每个项目组都应该有个项目进度墙,将自己组看的项目列在那里,然后每天通过项目墙看每个项目的进度,一旦某个项目有了进展,就派人去盯一下。

由于 Socket 是文件描述符,因而某个线程盯的所有的 Socket,都放在一个文件描述符集合 fd_set 中,这就是项目进度墙,然后调用 select 函数来监听文件描述符集合是否有变化。一旦有变化,就会依次查看每个文件描述符。那些发生变化的文件描述符在 fd_set 对应的位都设为 1,表示 Socket 可读或者可写,从而可以进行读写操作,然后再调用 select,接着盯着下一轮的变化。。

方式四:一个项目组支撑多个项目(IO 多路复用,从“派人盯着”到“有事通知”)

上面 select 函数还是有问题的,因为每次 Socket 所在的文件描述符集合中有 Socket 发生变化的时候,都需要通过轮询的方式,也就是需要将全部项目都过一遍的方式来查看进度,这大大影响了一个项目组能够支撑的最大的项目数量。因而使用 select,能够同时盯的项目数量由 FD_SETSIZE 限制。

如果改成事件通知的方式,情况就会好很多,项目组不需要通过轮询挨个盯着这些项目,而是当项目进度发生变化的时候,主动通知项目组,然后项目组再根据项目进展情况做相应的操作。

能完成这件事情的函数叫 epoll,它在内核中的实现不是通过轮询的方式,而是通过注册 callback 函数的方式,当某个文件描述符发送变化的时候,就会主动通知。

假设进程打开了 Socket m, n, x 等多个文件描述符,现在需要通过 epoll 来监听是否这些 Socket 都有事件发生。其中 epoll_create 创建一个 epoll 对象,也是一个文件,也对应一个文件描述符,同样也对应着打开文件列表中的一项。在这项里面有一个红黑树,在红黑树里,要保存这个 epoll 要监听的所有 Socket。
当 epoll_ctl 添加一个 Socket 的时候,其实是加入这个红黑树,同时红黑树里面的节点指向一个结构,将这个结构挂在被监听的 Socket 的事件列表中。当一个 Socket 来了一个事件的时候,可以从这个列表中得到 epoll 对象,并调用 call back 通知它。

这种通知方式使得监听的 Socket 数据增加的时候,效率不会大幅度降低,能够同时监听的 Socket 的数目也非常的多了。上限就为系统定义的、进程打开的最大文件描述符个数。因而,epoll 被称为解决 C10K 问题的利器

名词解释

文件描述符限制是指一个操作系统中能够同时打开的文件和网络连接的数量上限。为了理解这个概念,我们可以先了解什么是文件描述符,然后解释为什么它会限制并发 TCP 连接数。

什么是文件描述符?

在操作系统中,每个文件(包括网络连接)在打开时,都会被分配一个唯一的标识符,这个标识符就叫做文件描述符(File Descriptor,简称 FD)。文件描述符是一个非负整数,用来引用一个打开的文件或网络连接。

  • 文件:任何类型的文件,比如文本文件、图片文件等。
  • 网络连接:TCP 连接、UDP 连接等。
  • 其他资源:如管道、设备等。

文件描述符限制

操作系统对每个进程能够同时打开的文件描述符数量有限制,这是出于资源管理和安全的考虑。这个限制通常可以分为两个层次:

  1. 软限制:用户或进程可以更改的限制,一般默认较小,但可以通过修改系统设置或在程序中动态调整。
  2. 硬限制:系统级的限制,只有管理员可以更改,通常比软限制要大。

举个例子

假设你在编写一个服务器程序,这个服务器需要处理很多客户端的连接,每个连接对应一个文件描述符。

  • 默认限制操作系统可能默认限制每个进程只能打开 1024 个文件描述符。如果你有超过 1024 个客户端同时连接到服务器,新的连接将无法建立,因为文件描述符已经用完。
  • 调整限制:你可以通过修改系统配置来增加文件描述符的限制。例如,在 Linux 系统中,你可以通过修改 /etc/security/limits.conf 文件或使用 ulimit 命令来调整这个限制。

为什么文件描述符限制会影响并发连接数?

每个 TCP 连接在服务器端都需要一个文件描述符来表示和管理。如果文件描述符用完了,服务器将无法接受新的连接,即使硬件和其他资源还能够处理更多的连接。这就导致了并发 TCP 连接数远不能达到理论上的上限。


应用层协议

二、HTTP协议:看个新闻原来这么麻烦

HTTP 是基于 TCP 协议的,要先建立 TCP 连接
建立了连接以后,浏览器就要发送 HTTP 的请求。

HTTP 请求的创建

在这里插入图片描述

第一部分:请求行

GET POST PUT DELETE
POST 往往是用来创建一个资源的,而 PUT 往往是用来修改一个资源的。

第二部分:首部字段

例如,Accept-Charset,表示客户端可以接受的字符集。防止传过来的是另外的字符集,从而导致出现乱码。

再如,Content-Type是指正文的格式。例如,我们进行 POST 的请求,如果正文是 JSON,那么我们就应该将这个值设置为 JSON。

在 HTTP 协议中,Cache-ControlIf-Modified-Since 是用于控制缓存行为和条件请求的头字段。让我们通俗易懂地解释它们的作用和工作方式。

Cache-Control 头字段用于指定缓存机制的指令,这些指令告诉浏览器和中间缓存服务器如何缓存 HTTP 响应。它可以帮助提高网站性能和减少带宽消耗。

常见指令
  1. public:响应可以被任何缓存(包括浏览器、代理服务器等)缓存。

    • 例子Cache-Control: public
  2. private:响应只能被用户的浏览器缓存,不能被共享缓存(如代理服务器)缓存。

    • 例子Cache-Control: private
  3. no-cache:缓存可以存储响应,但在使用前必须先验证其有效性(向服务器发送请求确认)。

    • 例子Cache-Control: no-cache
  4. no-store:不允许缓存响应,所有内容每次都必须从服务器获取。

    • 例子Cache-Control: no-store
  5. max-age:指定响应在缓存中可以保存的最大时间(以秒为单位),在此时间内缓存内容被认为是新鲜的。

    • 例子Cache-Control: max-age=3600(缓存内容在1小时内有效)
场景:用户访问网页
  1. 第一次访问

    • 用户浏览器向服务器请求网页。
    • 服务器返回网页内容,并在响应头中包含 Cache-Control: max-age=3600Last-Modified 头字段。
    • 浏览器将网页缓存1小时。
  2. 在1小时内再次访问

    • 浏览器检查缓存,发现缓存仍然有效(未超过 max-age)。
    • 浏览器直接从缓存中加载网页,无需向服务器发送请求。
  3. 超过1小时再次访问

    • 浏览器向服务器发送请求,包含If-Modified-Since头字段,指示上次接收到的 Last-Modified 时间。
    • 服务器检查资源是否自该时间以来有修改:
      • 如果没有修改,返回 304 Not Modified,浏览器使用缓存内容。
      • 如果有修改,返回新的网页内容和新的 Last-Modified 时间,浏览器更新缓存。

HTTP 请求的发送

就是 TCP 传输

HTTP 2.0

HTTP/2 和 HTTP/1.1 是两个版本的超文本传输协议,它们有许多不同之处,主要目的是提高性能和效率。以下是 HTTP/2 和 HTTP/1.1 的主要区别,通俗易懂地解释这些技术细节:

1. 多路复用

  • HTTP/1.1:每个请求-响应对都需要一个独立的 TCP 连接。这意味着如果一个网页上有多个资源(如图片、CSS 文件、JavaScript 文件等),每个资源的请求通常需要单独的连接,导致了“队头阻塞”(Head-of-Line Blocking)问题:一个请求阻塞了,后续请求也无法进行。
  • HTTP/2:引入了多路复用技术,多个请求和响应可以在一个单一的 TCP 连接中同时进行。这样可以有效地利用网络资源,减少延迟。

2. 二进制分帧

  • HTTP/1.1:使用纯文本格式来传输数据,包括请求和响应头部。这种格式在解析时效率较低。
  • HTTP/2:使用二进制分帧层(Binary Framing Layer),将所有传输的信息(头部和数据)编码为二进制格式。这种方式更高效、解析更快,并且更容易实现多路复用。

3. 头部压缩

  • HTTP/1.1:每次请求都会携带完整的头部信息,头部信息往往很大且包含重复的内容,浪费了带宽。
  • HTTP/2:使用 HPACK 压缩算法对头部信息进行压缩,大大减少了头部的大小和冗余信息,提高了传输效率。

4. 服务器推送

  • HTTP/1.1:只有客户端可以主动请求资源,服务器只能被动响应。
  • HTTP/2:引入了服务器推送功能,服务器可以在客户端请求某个资源时,主动推送其他相关资源到客户端,这样客户端就不需要再单独请求这些资源了。例如,当客户端请求一个 HTML 页面时,服务器可以提前推送相关的 CSS 和 JavaScript 文件。

5. 流量控制

  • HTTP/1.1:没有针对流量控制的机制,所有请求-响应对共享带宽,可能导致性能不稳定。
  • HTTP/2:引入了流量控制机制,可以更好地管理和分配带宽,确保各个请求的传输速度和效率。

6. 优先级和依赖关系

  • HTTP/1.1:没有内置的请求优先级机制,所有请求的处理顺序主要取决于到达服务器的顺序。
  • HTTP/2:允许客户端为每个请求分配优先级,并建立依赖关系,使得重要的资源可以优先传输,优化了页面加载顺序和速度。
    在这里插入图片描述

QUIC

尽管 HTTP/2 引入了多路复用技术,使得多个流可以在一个 TCP 连接上并行传输,但由于底层使用的是 TCP 协议,TCP 必须保证数据包按顺序和完整性传输。如果某个数据包出现问题,整个连接上的所有数据传输都会被阻塞,直到问题数据包被正确重传和接收。这就意味着,即使在 HTTP/2 中,某个流的数据包出现问题,其他流的数据传输也会受到影响,无法完全避免队头阻塞的问题

于是,就又到了从 TCP 切换到 UDP。这就是 Google 的 QUIC 协议

机制一:自定义连接机制

我们都知道,一条 TCP 连接是由四元组标识的,分别是源 IP、源端口、目的 IP、目的端口。一旦一个元素发生变化时,就需要断开重连,重新连接。在移动互联情况下,当手机信号不稳定或者在 WIFI 和 移动网络切换时,都会导致重连,从而进行再次的三次握手,导致一定的时延。

这在 TCP 是没有办法的,但是基于 UDP,就可以在 QUIC 自己的逻辑里面维护连接的机制,不再以四元组标识,而是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。

机制二:自定义重传机制

三、

四、

五、

六、

七、

八、

九、

十、

相关文章:

网络协议二

一、套接字Socket 基于 TCP UDP 协议的 Socket 编程,在讲 TCP 和 UDP 协议的时候,我们分客户端和服务端,在写程序的时候,我们也同样这样分。 在网络层,Socket 函数需要指定到底是 IPv4 还是 IPv6,分别对应设…...

内存映射mmap技术详解

一、mmap基础概念 mmap 即 memory map,也就是内存映射。mmap 是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,…...

react 合成事件

React合成事件-CSDN博客 当然,很高兴为你解释React中的合成事件概念,非常适合React初学者理解。 想象一下,你正在组织一场派对,为了让派对顺利进行,你需要管理各种活动,比如游戏、音乐和食物分配。但是&a…...

springboot配置集成RedisTemplate和Redisson,使用分布式锁案例

文章要点 自定义配置属性类集成配置RedisTemplate集成配置分布式锁Redisson使用分布式锁简单实现超卖方案 1. 项目结构 2. 集成RedisTemplate和Redisson 添加依赖 依赖的版本与继承的spring-boot-starter-parent工程相对应&#xff0c;可写可不写 <!--spring data redis…...

随机数相关

产生随机数对象 固定写法&#xff1a; Random 随机数变量名 new Random();Random r new Random();生成随机数 int i r.Next(); //生成一个非负数的随机数 Console.WriteLine(i);i r.Next(100); // 生成一个 0~99的随机数 左边始终是0 左包含 右边是100 右不包含 Consol…...

EulerMaker Yocto Open Build Service

EulerMaker & Yocto & Open Build Service 1 介绍1.1 概述 2 工具2.1 Yocto 【嵌入式领域】介绍目标好处三大关键组件创建流程发行版本 2.2 Open Build Service 【OBS】【服务器领域】介绍应用 2.3 EulerMaker 【全场景】介绍特性需求背景&#xff08;1&#xff09;能支…...

SQL面试问题集

目录 Q.左连接和右连接的区别 Q.union 和 union all的区别 1、取结果的交集 2、获取结果后的操作 Q.熟悉开窗函数吗&#xff1f;讲一下row_number和dense_rank的区别。 Q.hive行转列怎么操作的 Q.要求手写的题主要考了聚合函数和窗口函数&#xff0c;row_number()&#…...

基于单片机的八路抢答器设计论文

绪 论1.1 课题研究的相关背景 抢答器是一种应用非常广泛的设备,在各种竞赛、抢答场合中,它能迅速、客观地分辨出最先获得发言权的选手。早期的抢答器只由几个三极管、可控硅、发光管等组成,能通过发光管的指示辩认出选手号码。现在大多数抢答器均使用单片机(如MCS-5…...

一个最简单基于spring的websocket服务端+客户端实现案例

1、服务端 代码分为两部分&#xff1a; 一个是服务器终端类&#xff1a;用java注解来监听连接ServerEndpoint、连接成功OnOpen、连接失败OnClose、收到消息等状态OnMessage import org.springframework.stereotype.Component;import javax.websocket.*; import javax.websoc…...

三.二、关于 Vue.js 中`transition`组件使用:页面切换动画和标签移动动画都是要用到的

一、引言 在 Vue.js 中&#xff0c;transition组件提供了一种简单而强大的方式来实现页面过渡效果。它可以让元素在状态改变时&#xff0c;如进入或离开视图时&#xff0c;以平滑的动画方式进行过渡。通过transition&#xff0c;我们可以为应用增添更加生动和吸引人的用户体验…...

指纹考勤系统

目录 1.课题研究目的和内容 1.1 课题研究目的 1.2 课题研究内容 2.系统总体方案设计及功能模块介绍 2.1总体方案设计 2.2 ATK-301模块介绍 2.3 TFTLCD显示功能模块介绍 2.4 蜂鸣器报警功能模块介绍 2.5 时钟模块介绍 3.系统硬件设计与实现 3.1 系统硬件电…...

怎么找抖音视频素材?下载抖音的素材视频网站分享给你

在这个视觉印象至关重要的时代&#xff0c;选用高质量的视频素材对于制作抖音视频来说是关键。如果你正在寻找适合的视频素材来丰富你的抖音创作&#xff0c;以下这份详细的视频素材网站指南将帮助你迈出第一步。 蛙学府网 蛙学府网提供了丰富多样的视频素材&#xff0c;包括动…...

【pytorch】大模型训练张量并行

Large Scale Transformer model training with Tensor Parallel (TP) 张量并行如何工作 原始 Tensor Parallel (TP) 模型并行技术于Megatron-LM论文中被提出&#xff0c;是一种用于培育大规模Transformer模型的高效模型并行技术。我们在本练习指南中介绍的序列并行 (SP) 实际…...

Flutter 中的 CupertinoSliverNavigationBar 小部件:全面指南

Flutter 中的 CupertinoSliverNavigationBar 小部件&#xff1a;全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架&#xff0c;它允许开发者使用 Dart 语言来构建高性能、美观的移动、Web 和桌面应用。在 Flutter 的丰富组件库中&#xff0c;CupertinoSliverNavigation…...

【数据库系统概论】程序题

“学生管理数据库”包含以下三个表&#xff0c;即学生表Student、课程表Course和选课表SC&#xff0c;结构如下&#xff1a; Student&#xff08;Sno&#xff0c;Sname&#xff0c;Ssex&#xff0c;Sage&#xff0c;Sdept&#xff09;Course &#xff08;Cno&#xff0c;Cname&…...

群体优化算法---蝙蝠优化算法分类Iris数据集

介绍 蝙蝠算法&#xff08;Bat Algorithm, BA&#xff09;是一种基于蝙蝠回声定位行为的优化算法。要将蝙蝠算法应用于分类问题&#xff0c;可以通过将蝙蝠算法用于优化分类器的参数&#xff0c;图像分割等 本文示例 我们使用一个经典的分类数据集&#xff0c;如Iris数据集&…...

【C++】类和对象1.0

本鼠浅浅介绍一些C类和对象的知识&#xff0c;希望能得到读者老爷们的垂阅&#xff01; 目录 1.面向过程和面向对象 2.类的引入 3.类的定义 4.类的访问限定符及封装 4.1.类的访问限定符 4.2.封装 5.C中struct和class的区别 6.类域 7.类的实例化 8.类对象模型 8.1.类…...

Linux下gcc编译32位程序报错

gcc使用-m32选项&#xff0c;编译32位程序时&#xff0c;报错&#xff1a;/usr/include/stdio.h:27:10: fatal error: bits/libc-header-start.h: No such file or directory gcc编译32位程序时&#xff0c;报错&#xff1a;/usr/include/stdio.h:27:10: fatal error: bits/li…...

godot.bk

1.搜索godot国内镜像&#xff0c;直接安装&#xff0c;mono是csharp版本 2.直接解压&#xff0c;50m&#xff0c;无需安装&#xff0c;直接运行 3.godot里分为场景&#xff0c;节点 主场景用control场景&#xff0c;下面挂textureact放背景图片&#xff0c;右键实例化子场景把…...

【C++修行之道】类和对象(三)拷贝构造函数

目录 一、 概念 二、特征 正确的拷贝构造函数写法&#xff1a; 拷贝函数的另一种写法 三、若未显式定义&#xff0c;编译器会生成默认的拷贝构造函数。 四、编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了&#xff0c;还需要自己显式实现吗&#xff1f; 深拷…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...