UNIX网络编程-传输层

概述


传输层主要包括:TCP、UDP、SCTP(流控制传输协议)!

绝大多数客户端/服务器网络应用都使用TCP/UDP。SCTP是一个较新的协议,最初设计用于跨因特网传输电话信令。

这些传输协议都转而使用网络协议IP:或是IPv4,或是IPv6。尽管可以绕过传输层直接使用IPv4或IPv6,但这种技术(往往称为原始套接字)却极少使用。

UDP是一个简单的、不可靠的数据报协议,而TCP是一个复杂、可靠的字节流协议。SCTP与TCP类似之处在于它也是一个可靠的传输协议,但它还提供消息边界、传输级别多宿支持以及将头端阻塞减少到最小的一种方法。

必须了解这些传输层协议提供给应用进程的服务,才能弄清这些协议处理什么,应用进程中又需要处理什么。

下面主要讲述:TCP的三次握手、TCP的连接终止序列和TCP的TIME_WAIT状态,SCTP的四次握手和SCTP的连接终止,加上由套接字层提供的TCP、UDP和SCTP缓冲机制等等。

用户数据报协议(UDP)


UDP是一个简单的传输层协议。应用进程往一个UDP套接字写入一个消息,该消息随后被封装到一个UDP数据报,该UDP数据报进而又被封装为一个IP数据报,然后发送到目的地。

注意:

UDP不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨网络后保持不变,也不保证每个数据报只到达一次。

我们使用UDP进行网络编程所遇到的问题是它缺乏可靠性。

如果一个数据报到达了其最终目的地,但是校验和检测发现有错误,或者该数据报在网络传输中被丢弃了,它就无法被投递给UDP套接字,也不会被源端自动重传。如果想要确保一个数据报到达其目的地,可以往应用程序中添置一大堆的特性:来自对端的确认、本端的超时与重传等。

每个UDP数据报都有一个长度。如果一个数据报正确地到达其目的地,那么该数据报的长度将随数据一道传递给接收端应用进程。

注意:

  1. “上述所说的数据报到达其最终目的地”是指数据报被接收端的网络接口接收,并且被路由到正确的IP地址上,但并未将其传递给UDP套接字(应用层)。
  2. UDP是无连接的服务,因为UDP客户端与服务器之间不必存在任何长期的关系。举例来说,一个UDP客户端可以创建一个套接字并发送一个数据报给一个给定的服务器,然后立即用同一个套机字发送另一个数据报给另一个服务器。同样地,一个UDP服务器可以用同一个UDP套接字从若干个不同的客户端接受数据报,每个客户端一个数据报。

传输控制协议(TCP)


TCP提供客户端与服务器之间的连接。TCP客户端先与某个给定的服务器建立连接,再使用该连接与服务器交换数据,然后终止这个连接。

TCP提供了可靠性。当TCP向另一端发送数据时,它要求对端返回一个确认。如果没有收到确认,TCP就自动重传数据并等待更长的时间。在数次重传失败后,TCP才放弃,如此在尝试发送数据上所花的总时间一般是4~10分钟(依赖于具体实现)。

 注意:

TCP也不是100%可靠的协议,它提供的是数据的可靠性或故障的可靠通知。

动态估算(RTT)

TCP含有用于动态估算客户端与服务器之间的往返时间(round-trip time,RTT)的算法,以便它知道等待一个确认需要多少时间。

举例来说,RTT在一个局域网上大约是几毫秒,跨越一个广域网则可能是数秒钟。另外,因为RTT受网络流通各种变化因素影响,TCP还持续估算一个给定连接的RTT。

数据排序

TCP通过给其中每个字节关联一个序列号对所发送的数据进行排序。

举例来说,假设一个应用写2048字节到一个TCP套接字,导致TCP发送2个分节:

  1. 第一个分节所含数据的序列号为1~1024。
  2. 第二个分节所含数据的序列号为1025~2048。

注意:

  1. 分节是TCP传递给IP的数据单元。
  2. 如果这些分节非顺序到达,接收端TCP将先根据它们的序列号重新排序,再把结果数据传递给接收应用。
  3. 如果接收端TCP收到来自对端的重复数据(譬如对端认为一个分节已丢失并因此重传,而这个分节并没有真正丢失,只是网络通信过于拥挤),它可以根据序列号判定数据是重复的,从而丢弃重复数据。

 流量控制

TCP提供流量控制(flow control)。TCP总是告知对端,在任何时刻它一次能够从对端接受多少字节的数据,这称为通告窗口。

在任何时刻,该窗口指出接收缓冲区中当前可用的空间量,从而确保发送端发送的数据不会使接收缓冲区溢出。

该窗口时刻动态变化:当接收到来自发送端的数据时,窗口大小就减小,但是当接收端应用从缓冲区中读取数据时,窗口大小就增大。

通告窗口大小减小到0是有可能的:当TCP对应某个套接字的接收缓冲区已满,导致它必须等待应用从该缓冲区读取数据时,方能从对端再接受数据。

TCP连接是全双工的,这意味着在一个给定的连接上,可以在任何时刻在进出两个方向上既发送数据又接收数据。因此,TCP必须为每个数据流方向跟踪诸如序列号和通告窗口大小等状态信息。

建立一个全双工连接后,需要的话可以把它转换成一个单工连接。

注意:

  1. UDP不提供流量控制,让较快的UDP发送端以一个UDP接收端难以跟上的速度发送数据报是非常容易的。
  2. UDP可以是全双工的。

流控制传输协议(SCTP)


SCTP在客户端可服务器之间提供关联,并像TCP那样给应用提供可靠性、排序、流量控制以及全双工的数据传送。

 问1:SCTP和TCP的区别是什么?

答:二者区别如下:

  1. SCTP中使用“关联”一词取代“连接”是为了避免这样的内涵:一个连接只涉及两个IP地址之间的通信。一个关联指代两个系统之间的一次通信,它可能因为SCTP支持多宿而涉及不止两个IP地址。
  2. TCP是面相字节流的,而SCTP是面向消息的。它提供各个记录的按序递送服务。与UDP一样,由发送端写入的每条记录的长度随数据一道传递给接收端应用。
  3. SCTP能够在所连接的端点之间提供多个流,每个流各自可靠地按序递送消息。一个流上某个消息的丢失不会阻塞同一关联其他流上消息的投递。这种做法与TCP刚好相反,就TCP而言,在单个字节流中任何位置的字节丢失都将阻塞该连接上其后所有数据的递送,直到该丢失被修复为止。

此外,SCTP还提供多宿特性,使得单个SCTP端点能够支持多个IP地址。该特性可以增强应对网络故障的健壮性。

问2:SCTP的多宿特性是指什么?多流特性又是指什么?

  1. 多宿特性是指一个SCTP端点可以通过多个IP地址到达。这意味着两个SCTP端点在建立关联后,数据可以通过不同的物理通路进行传送。例如,一个服务器可能同时拥有有线网络接口和无线网络接口,当有线网络出现故障时,SCTP可以自动切换到无线网络接口继续传输数据,从而提高数据传输的可靠性和灵活性。
  2. 多流特性是指SCTP支持在一个关联中建立多个独立的流,每个流都可以独立地进行数据传输(每个请求都被分配到一个独立的流中处理)。这种特性使得SCTP能够更有效地利用网络资源,提高数据传输的并行性和效率。

注:多宿特性意在增强网络健壮性,所以多宿中的多个IP地址通常是指一台物理设备上的不同网络接口。

TCP在路由协议的辅助下,也可以获取类似的健壮性。

SCTP的多宿特性允许主机(而不仅仅是路由器)也多宿,而且允许多宿跨越不同的服务供应商发生,这些基于路由的TCP多宿方法都无法做到。

TCP连接的建立和终止


三次握手

建立一个TCP连接时会发生如下情形:

  1. 服务器必须准备好接受外来的连接。这通常通过调用socket、bind、listen这3个函数来完成,我们称之为被动打开。
  2. 客户端通过调用connect发起主动打开。这导致客户端TCP发送一个SYN(同步)分节,它告诉服务器客户端将在(带建立的)连接中发送的数据的初始序列号。通常SYN分节不携带数据,其所在IP数据报只含有一个IP首部、一个TCP首部以及可能有的TCP选项。
  3. 服务器必须确认(ACK)客户端的SYN,同时自己也得发送一个SYN分节,它含有服务器将在同一连接中发送的数据的初始序列号。服务器在单个分节中发送SYN和对客户端SYN的ACK(确认)。
  4. 客户端必须确认服务器的SYN。

这种交换至少需要3个分组,因此称之为TCP的三次握手。

注意:

  1. 上图中给出的客户端的初始序列号为J,服务器的初始序列号为K。ACK中的确认号是发送这个ACK的一端所期待的下一个序列号。
  2. 因为SYN占据一个字节的序列号空间,所以每一个SYN的ACK中的确认号就是该SYN的初始序列号加1。类似地,每一个FIN(表示结束)的ACK中的确认号为该FIN的序列号加1。

扩展:

建立TCP连接就好比一个电话系统。socket函数等同于有电话可用。bind函数是在告诉别人你的电话号码,这样他们可以呼叫你。listen函数是打开电话振铃,这样当有一个外来呼叫到达时,你就可以听到。connect函数要求我们知道对方的电话号码并拔打它。accept函数发生在被呼叫的人应答电话之时。由accept返回客户端的标识(即客户端的IP地址和端口号)类似于让电话机的呼叫者ID功能部件显示呼叫者的电话号码。然而两者的不同之处在于accept只在连接建立之后返回客户的标识,而呼叫者ID功能部件却在我们选择应答或不应答电话之前显示呼叫者的电话号码。如果使用域名系统DNS(见第11章),它就提供了一种类似于电话薄的服务。getaddrinfo类似于在电话薄中查找某个人的电话号码,getnameinfo则类似于有一本按照电话号码而不是按照用户名排序的电话薄。

四次挥手

TCP建立一次连接需要3个分节,终止一个连接需要4个分节。

四次挥手流程如下:

  1. 某个应用进程首先调用close,称该端执行主动关闭。该端的TCP于是发送一个FIN分节,表示数据发送完毕。
  2. 接收到这个FIN的对端执行被动关闭。这个FIN由TCP确认。它的接收也作为一个文件结束符传递给接收端应用进程(放在已排队等候该应用进程接收的任何其他数据之后),因为FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。
  3. 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
  4. 接收这个最终FIN的原发送端TCP(即执行主动关闭的一端)确认这个FIN。

注意:

  1. 因为每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。之所以说通常,是因为某些情形下步骤1中的FIN可能会随着数据一起发送。另外,步骤2和步骤3发送的分节都出自执行被动关闭的一端,有可能被合并为一个分节。
  2. 类似SYN,一个FIN也占1个字节的序列号空间。因此,每个FIN的ACK确认号就是这个FIN的序列号加1。
  3. 在步骤2和步骤3之间,从执行被动关闭一端到执行主动关闭一端流动数据是可能的,这被称为半关闭。
  4. 无论是客户端还是服务器,任何一端都可以执行主动关闭。

当套接字被关闭时,其所在端TCP各自发送了一个FIN,这是由应用进程调用close而发生的。

当一个Unix进程无论自愿地(调用exit或从main函数返回)还是被动地(收到一个终止本进程的信号)终止时,所有打开的描述符都会被关闭,这也导致仍然打开的任何TCP连接上也发出一个FIN。

TCP状态转换图

TCP涉及连接建立和连接终止的操作可以用状态转换图来表示:

TCP为一个连接定义了11种状态,并且TCP规则规定如何基于当前状态及在该状态下所接收的分节从一个状态转换到另一个状态。

示例:

当某个应用进程在CLOSED状态下执行主动打开时,TCP将发送一个SYN,且新的状态是SYN_SENT。如果这个TCP接着接收到一个带ACK的SYN,它将发送一个ACK,且新的状态是ESTABLISHED。这个最终状态是绝大多数数据传送发生的状态。

自ESTABLISHED状态引出的两个箭头处理连接的终止:

  1. 如果某个应用进程在接收到一个FIN之前调用close(主动关闭),那就转换到FIN_WAIT_1状态。
  2. 如果某个应用进程在ESTABLISHED状态期间接收到一个FIN(被动关闭),那就转换到CLOSE_WAIT状态。

图中存在两个未曾讨论过的状态:同时打开(发生在两端几乎同时发送SYN并且这两个SYN在网络中交错的情形下)、同时关闭(发生在两端几乎同时发送FIN的情形下)。

 注意:

  1. 粗实线:表示客户端状态转换。
  2. 粗虚线:表示服务器状态转换。
  3. 应用:表示状态转换在应用进程发起操作时发生。
  4. 接收:表示状态转换在接收到分节时发生。
  5. 发送:表示这个转换发送过什么。

观察分组

下图展示了一个完整的TCP连接所发生的实际分组交换情况,包括连接建立、数据传送和连接终止3个阶段。图中还展示了每个端点所经历的TCP状态:

 注意:

  1. 客户端通告值为536的MSS,表明客户端只实现了最小重组缓冲区大小,即客户端接收数据的单个分节为536字节。
  2. 服务器通告值为1460的MSS(以太网上的IPv4的典型值),即服务器接收数据的单个分节为1460字节。
  3. 不同方向上MSS值可以不相同。

  1. 建立连接(三次握手,3个分节)。
  2. 成功建立一个连接后,客户端就构造一个请求并发送给服务器。这里假设该请求适合于单个TCP分节(即请求大小小于服务器通告的值1460字节的MSS)。服务器处理该请求并发送一个应答,假设该应答也适合于单个分节(即小于536字节)。图中箭头表示这两个数据分节。
  3. 终止连接(四次挥手,4个分节)。

注意:

  1. 服务器对客户端请求的确认是伴随其应答发送的。这种做法称为捎带,它通常在服务器处理请求并产生应答的时间少于200ms时发生。如果服务器处理请求并产生应答的时间较长,如1s,则会先确认后应答。

 问:网络应用是选择TCP还是UDP?

答:从上图可知,如果该连接的整个目的仅仅是发送一个单分节的请求和接收一个单分节的应答,那么使用TCP有8个分节的开销(除了请求和应答两个分节)。如果改用UDP,那么只需要交换两个分组:一个承载请求,一个承载应答。然而从TCP切换到UDP将丧失TCP提供的全部可靠性,迫使可靠服务的一大堆细节从传输层(TCP)转移到UDP应用层。此外,TCP提供的另一个重要特性即拥塞控制也必须由UDP应用进程来处理。

尽管如此,仍然有许多网络应用是使用UDP构建的,因为UDP需要交换的数据量较少,而且UDP避免了TCP连接建立和终止所需要的开销。

TIME_WAIT状态


TIME_WAIT状态通常发生在主动关闭的一端,且该状态持续时间是最长分节生命期(maximum segment lifetime,MSL)的两倍,有时候称之为2MSL。

任何TCP实现都必须为MSL选择一个值,RFC的建议值是2分钟,不过源自Berkeley的实现传统上改用30秒,这意味着TIME_WAIT状态的持续时间在1分钟到4分钟之间。MSL是任何IP数据报能够在因特网中存活的时间。

 问:TIME_WAIT状态的作用是什么?

答:TIME_WAIT状态有两个存在的理由:

  1. 可靠地实现TCP全双工连接的终止。
  2. 允许老的重复分节在网络中消逝。

第一个理由解释:

假设上图中最后一个ACK丢失了,服务器将重新发送最终那个FIN,因此客户端必须维护状态信息,以允许它重新发送最终那个ACK。如果客户端不维护状态信息,它将响应一个RST(另一种类型的TCP分节),该分节将被服务器解释成一个错误。

第二个理由解释:

假设在12.106.32.254的1500端口和206.168.112.219的21端口之间有一个TCP连接。关闭这个连接后,在相同的IP地址和端口号之间建立另一个连接。后一个连接称为前一个连接的化身,因为它们的IP地址和端口号都相同。TCP必须防止来自上一个已终止的连接的重复分组在该连接中再现。而TIME_WAIT状态的持续时间是2MSL,这就足以让上一个连接中的分组最多存活MSL秒即被丢弃,另一个方向上的应答最多存活MSL秒也被丢弃。

 注意:

上述所说的重复分组是指:发送端在发送一个TCP分节后,由于某个路由器崩溃或某两个路由器之间的某个链路断开时,路由协议需要花费数秒钟到数分钟的时间才能稳定并找到另一条通路,在这段时间内可能会超时重传该TCP分节,而重传的TCP分节却通过某条候选路径达到最终目的地。然而不久后(自迷途的TCP分节开始其旅程起最多MSL秒以内),路由循环被修复,早先迷失的TCP分节最总也被送到目的地,此时该分节被称为迷途的重复分组或漫游的重复分组。

端口号


任何时候,多个进程可能同时使用TCP、UDP和SCTP这3中传输层协议中的任何一种。这3种协议都使用16位整数的端口号来区分这些进程。

IANA(因特网已分配数值权威机构)维护着一个端口号分配状况的清单。端口号被划分为以下3段:

  1. 众所周知的端口为0~1023:这些端口由IANA分配和控制。可能的话,相同端口号就分配给TCP、UDP和SCTP的同一给定服务。例如,不论是TCP还是UDP端口号80都被赋予Web服务器,尽管它目前的所有实现都单纯使用TCP。
  2. 已登记的端口为1024~49151:这些端口不受IANA控制,不过由IANA登记并提供它们的使用情况。可能的话,相同端口号也分配给TCP和UDP的同一给定服务。例如,6000~6063分配给这两种协议的X Windows服务器,尽管它的所有实现当前单纯使用TCP。49151这个上限的引入是为了给临时端口号留出范围。
  3. 动态的或私用的端口为49152~65535:IANA不管这些端口,也即临时端口(49152这个魔数是65536的四分之三)。

端口号的划分和常见的分配情况:

 注意:

Unix系统有保留端口的概念,是指小于1024的任何端口(IANA众所周知的端口),这些端口只能赋予特权用户进程的套接字,且分配使用这些端口的服务器必须以超级用户特权启动。

套接字对

一个TCP连接的套接字对是一个定义该连接的两个端点的四元组:本地IP地址、本地TCP端口、外地IP地址、外地TCP端口。套接字对唯一标识一个网络上的每个TCP连接。

就SCTP而言,一个关联由一组本地IP地址、一个本地端口、一组外地IP地址、一个外地端口标识。在两个端点均非多宿的情形下,SCTP与TCP所用的四元组套接字对一致。然而在某个关联的任何一个端点为多宿的情形下,同一个关联可能需要多个四元组标识(这些四元组的IP地址各不相同,但端口号是一样的)。

标识每个端点的两个值(IP地址和端口号)通常称为一个套接字。

TCP端口号与并发服务器


并发服务器中主服务器循环通过派生一个子进程来处理每个新的连接。

并发服务器示例:

假设服务器的套接字对为{ * : 21, * : *},其中第一个星号表示未指定服务器的IP地址(服务器主机是多宿的),后面两个星号分别表示外地IP地址和端口号。

TCP端口号与并发服务器通信流程:

1)假设在IP地址为206.168.112.219的主机上启动第一个客户端(假设TCP选择的临时端口为1500),它对服务器的IP地址之一12.106.32.254执行主动打开。

2)当服务器接收并接受这个客户端连接时,它会fork一个自身副本,让子进程来处理该客户端的请求,如图所示。

3)假设在客户端主机上另有一个客户请求连接到同一个服务器。客户端主机的TCP为这个新客户的套接字分配一个未使用的临时端口1501,如图所示。

 注意:

  1. 服务器上这两个连接是有区别的:第一个连接的套接字对和第二个连接的套接字对不一样,因为客户端的TCP给第二个连接选择了一个未使用的端口1501。
  2. TCP无法仅仅通过查看目的端口号来分离外来的节点到不同的端点。它必须查看套接字对的所有4个元素才能确定由哪个端点接收某个到达的分节。
  3. 上图中对于同一个本地端口(21)存在3个套接字:{ 12.106.32.254 : 21, 206.168.112.219 : 1500}(第一个子进程)、{ 12.106.32.254 : 21, 206.168.112.219 : 1501}(第二个子进程)、{ * : 21, * : *}(父进程)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VScode分文件编写报错 | 如何进行VScode分文件编写 | 小白也能轻松解决版

分文件编写遇到的问题 分文件编写例子如下所示: 但是直接使用 Run Code 或者 调试C/C文件 会报错如下: 正在执行任务: C/C: g.exe 生成活动文件 正在启动生成… cmd /c chcp 65001>nul && D:\Librarys\mingw64\bin\g.exe -fdiagnostics-col…

计算机网络——传输层服务

传输层会给段加上目标ip和目标端口号 应用层去识别报文的开始和结束

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十五集:制作更多地图,更多敌人,更多可交互对象

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、第一个代表性场景 1.制作更多敌人2.制作更多可交互对象二、第二个代表性场景 1.制作更多敌人2.制作更多可交互对象三、第三个代表性场景 1.制作更多敌人2.制…

MongoDB安装配置及配置和启动服务

MongoDB 安装配置 附:MongoDB官网下载地址: https://www.mongodb.com/download-center/community 注: 官网可以下载最新版的MongoDB安装包,有MSI安装版和ZIP安装版。我们课堂上使用4.4.4的ZIP安装版。安装版参考博客&#xff1…

【redis】基础指令|数据结构总览|单线程架构分析

W...Y的主页 😊 代码仓库分享💕 前言:redis系类博客都是以redis5.0版本为基础!!! 目录 Redis常见命令 基本全局命令 KEYS EXISTS DEL EXPIRE TTL TYPE 数据结构和内部编码 单线程架构 Redis…

群控系统服务端开发模式-数据库设计图

根据整理的业务需求可以发现,本系统数据库针对1.0版本就分两种库。第一类是管理层的数据库,分别是管理员表、角色表、菜单表、部门表、级别表。分别对应控制权限及数据权限。 一、管理层数据库设计图 二、业务层数据库设计图

潜水定位通信系统的功能和使用方法_鼎跃安全

潜水定位通信系统是保障潜水安全与作业高效的关键设备。它利用先进的声呐、无线电等技术,可精准定位潜水员位置。在水下能实现潜水员之间以及与水面的双向通信,确保信息及时传递。具备高可靠性和稳定性,即使在复杂水环境中也能正常运行。 一、…

智能体能和人工智能有什么区别?

智能体与人工智能(AI)之间存在明显的区别,尽管两者在技术和应用上有一定的重叠。 一、定义与范畴 人工智能(AI) 人工智能是指通过模拟、延伸和扩展人的智能,使计算机或其他智能设备具有人类智能的一种技术…

Redis --- 第六讲 --- 关于持久化

前言 持久化:MySQL的事务,有四大比较核心的特性 1、原子性 2、一致性 3、持久性 》 把数据存储到硬盘上 》持久,把数据存储在内存上》持久化。重启进程/重启主机之后,数据是否存在。 4、隔离性 Redis是一个内存数据库&#…

如何在忘记密码的情况下解锁 iPhone? 6 种方法分享

您是否因为没有密码而无法解锁您的 iPhone? 别担心,这种情况比你想象的更常见!忘记密码是 iPhone 用户面临的最常见问题之一,而且可能非常令人沮丧 - 但不要绝望。 在这篇文章中,我们将与您分享绕过 iPhone 屏幕密码…

No provider available from registry RegistryDirectory

【中】No provider available from registry RegistryDirectory Dubbo 3.2.9Nacos 2.1.0 最近在做配置文件升级,服务比较多,之前的Dubbo配置各个服务写的比较乱,有的用Nacos上的 data-id,有的又是在自己的服务引入配置 遂准备统一…

记录一次从nacos配置信息泄露到redis写计划任务接管主机

经典c段打点开局。使用dddd做快速的打点发现某系统存在nacos权限绕过 有点怀疑是蜜罐,毕竟nacos这实在是有点经典 nacos利用 老规矩见面先上nacos利用工具打一波看看什么情况 弱口令nacos以及未授权访问,看这记录估计被光顾挺多次了啊 手动利用Nacos-…

软件测试与软件缺陷的基础知识

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

秋招面试题记录_半结构化面试

c八股(可能问的多一点) 1.简单说说C11语法特性 答: 1.auto以及decltype自动类型推导,避免手动声明复杂类型,减少冗长代码提升了可读性和安全性。 2.智能指针 自动释放内存 (具体说说) 有shared和unique 差异主要体现在所有权、内存开销、…

Tesseract OCR 安装

Tesseract OCR 的安装步骤因操作系统的不同而有所区别。以下是针对 Windows、macOS 和 Linux 系统的详细安装指导。 1. Windows 步骤: 下载 Tesseract 安装程序 访问 Tesseract GitHub Release 页面。下载最新版本的安装程序(例如 .exe 文件&#xff0…

【小趴菜前端实习日记5】

实习日记5 一、vue3中如何使用router(获取this)二、ts中用object定义类型太宽泛导致Ts无法推断出正确类型三、动态设置日记封面失败vite动态引入静态资源1.方法一vue3父子组件生命周期执行顺序 2.方法二3.方法三 四、打包问题总结1.The import.meta meta-property i…

整理—Redis

目录 Redis底层的数据结构 ZSet用过吗 Zset 底层是怎么实现的 跳表是怎么实现的? Redis为什么使用跳表而不是用B树? 压缩列表是怎么实现的? Redis 中的 listpack 哈希表是怎么扩容的? String 是使用什么存储的 Redis为什么快&#xf…

最好的ppt模板网站是哪个?做PPT不可错过的18个网站!

现在有很多PPT模板网站,但真正免费且高质量的不多,今天我就分享主流的国内外PPT模板下载网站,并且会详细分析这些网站的优缺点,这些网站都是基于个人实际使用经验的,免费站点会特别标注,让你可以放心下载&a…

C++:模板(2)

目录 非类型模板参数 模板的特化 概念 函数模板特化 类模板特化 全特化 偏特化 模板的分离编译 分离编译的概念 模板的分离编译 ​编辑 模板总结 非类型模板参数 模板参数分为类型形参与非类型形参。 类型形参:在模板参数列表中,跟在class…

STM32L1x 片上温度传感器采用ADC及工厂校准数据提升测量温度精度

背景 由于项目临时需要温度数据,又不想改动硬件了,反正对温度精度要求不算太高,索性就用MCU片上温度传感器的温度,来替代了。这里自己根据网上帖子做了一些测试用例尝试测温,但是,效果都不理想。发现ST官方…