[计算机网络]运输层概述
虽然我自己也不知道写在前面和前言有什么区别.....
这个系列其实是针对<深入浅出计算机网络>的简单总结,加入了一点个人的理解和浅薄见识,如果您有一些更好的意见和见解,欢迎随时协助我改正,感激不尽啦.
最近心态平和了不少, 和过去也完全做了个割舍吧,既然痛苦和压力的源头是曾经的爱和信任,那么就当这些从未出现过好了...
0.写在前面
在先前的时候,我们解释了网络层,数据链路层,物理层,其实这三个层理论上已经构建出了我们熟悉的计算机网络的体系结构了,我们知道计算机和计算机之间是如何实现链接,寻址,以及拓扑结构如何构建. 而接下来的两个层, 个人认为是更偏向于用户,或者是程序员的两层,我们需要具体确定用户使用了什么进程, 采取了什么服务,应该怎么样分配,基于完善的计算机网络结构真正意义上实现一些网络应用.
1.什么是运输层
1.1:运输层的任务
在教学模型中,运输层是自上而下的第二层,主要任务是为了相互通信的进程完成服务, 进程是计算机上运行的程序,在这一章节姑且可以这样理解(肯定是不贴切的,不过我相信学过操作系统的大家能理解我的意思, 对吧?)
在这一层中,真正通信的实体不是链接在网络上的计算机,而是计算机上的程序,如果看图可以发现大概是这样子的:
从图上来看,确确实实是将计算机网络的作用范围又扩大了一层,虽然这一个扩大范围来物理意义上是没啥变化的, 但是在逻辑上确实解决了很多问题. 我们将这个服务范围范围称之为:"运输层之间负责的是各个机器上进程的逻辑通信",此时PDU为根据所使用协议的不同,内容也不一样,这个将会在后面加以解释.
1.2.端口
(如果你之前进行过一定的后端服务和前端请求工作,这一小节可以不看)
我们知道,运行在计算机上的进程必然会存在一个标识符号:PID(进程标识符), 通过这个东西我们就可以在服务的时候区分不同的进程.
但是不同的计算机系统上,对于PID有不同的格式区分,例如在window上是10000这样子,在linux上是abcde(这里就是举个例子肯定不是这样的), 我们想要从一个进程发送到另一个进程的时候就容易发生这种尴尬的局面:
因此这就是端口存在的意义,端口虽然是只有本地意义,但是在指向地址的时候必然是统一格式的明确形式.用来标记各个应用进程.
其实编写过网络应用的同志,对这个东西多少应该是不陌生的.端口代表了进程接收服务的地方,通过端口可以访问到一些服务.如图所示
通过特定的端口,我们访问了该计算机上的运行在3030的端口,该端口上的进程返回给了我们一个html文件,这就是端口的作用.
一般来说,一个端口代表了一个进程对外访问的窗口.注意,这里的端口和数据链路层中提到的物理意义的端口不是一个东西,只能说毫无联系.
端口的长度为16比特,换算成十进制以后差不多就是-065535,主要分为三种形式,但是这里不是什么需要记忆的要点:
(1)熟知端口号/全球通用端口号:分配数值为0-1024,这部分端口号大多数是约定俗称一些东西, 在一开始进行分配的时候就已经制定了默认的进程和功能/协议,比如80端口默认为http, 443端口默认为https这样子.
(2)登记端口号:使用这类端口号需要进行一定的登记,并且没有指定默认的进程
(3)短暂端口号:这种端口号仅仅提供给用户端使用,由客户进程进行动态选择,并且在链接结束以后会进行回收.
1.3:提供的服务以及两种核心协议:
对于传输层来说,提供的服务就是像应用层的实体屏蔽了网络传输的细节,让应用进程无需担心具体的网络结构和路径.根据需求的不同,运输层向上提供两种服务,分别是可靠和不可靠传输.
与之对应的两种协议,估计大家也都耳熟能详了:
面向连接的控制传输协议(UDP)
无链接的用户数据报协议(TCP)
分别提供不可靠和可靠两种服务,.并且对应着应用层不同的协议类型(比如TCP向上对应的是HTTP,HTTPS,而UDP向上对应的是DNS,RTP等等).其中UDP的特点是无需链接,TCP的特点就是俗称的"三次握手,三次挥手"的链接构建释放规则.
并且,由于在本层中选择的协议各有不同,因此本层的PDU也会随着协议发生一些变化,例如最常用的TCP对应的数据单元被称为TCP报文段(Segment), UDP对应的数据单元也被乘坐UDP报文或者UDP数据报(User Datagram) .
这两个协议具体的区别和联系会在后面进行说明
1.4:复用,分用
复用和分用这两个概念其实有点怪的,不过其实倒也还好理解,简单来说就是复用是从上到下不断封装的过程,分用是根据自身的协议字段或者是端口号,向上交付给服务实体的过程
首先是复用:
发送方根据使用的不同报文,使用端口号来识别应用进程,并且使用对应的协议进行封装.在运输层使用TCP,即称之为"TCP"复用, UDP的则称之为UDP复用 .
然后在网络层使用IP数据报进行封装,这个操作被称为"IP复用"
然后是分用:
分用其实按照我的理解 , 就是对于上述复用过程的反方向过程.
IP分用: 网际层在接收到分组以后 , 会根据其中的协议字段将其解析为某个协议对应的数据单元 , 并且将这个数据单元交付给运输层对应的协议.
TCP分用: 运输层接收到TCP数据报以后 , 根据其中的端口字段,将其转交给对应的进程.
UDP分用: 同上;
其实画个图也很好理解
这个是官图....我再画一个比较理解的图
这张图上展示了IP和TCP的复用分用过程,结合上面的图,你应该能看出这个东西的具体逻辑
2.UDP和TCP,以及对比
前排说明,由于TCP的内容结构复杂的多,所以会放在第三部分讲解TCP的相关机制.
但是UDP十分简单,根本不用考虑有关于可靠传输的事情,所以这一个小部分就能说完.
稍安勿躁,慢慢来就是了
2.1. 无连接的UDP:
UDP是无连接的,换句话说,UDP的通信双方再进行数据交互之前是不需要任何链接操作的,只管发送,也不需要什么应答,随时可以发送,随时可以接收.
并且UDP是支持广播的,换句话说UDP支持一对多的操作
2.2.1:UDP对于应用层报文的处理:
对于上层发来的应用层报文,也就是SDU,UDP的选择是直接将数据报文包装一个UDP头部并且向下发送完整的UDP报文 . 由此可见,UDP对于数据的处理是保留报文的边界,换句话说,UDP是面向应用报文的,也就是单纯的封包和拆包
2.2.2:UDP对于数据可靠性的支持:
写这个标题 ≠ UDP支持可靠的数据传输
不等式秒了
UDP数据包无视这些东西,随之带来的就是更加简单的操作和应用,比如实时应用,直播,语音什么的.
2.2.3:UDP的首部格式
由于事情少,所以UDP的首部格式异常简单:仅有固定的八个字节
源端口和目的端口:这两个不用解释,很容易就可以说明了
长度:长度用于指明整个UDP用户数据报的长度
检验和:这里需要补充一个很重要的点,对于TCP和UDP来说, 检验和处理检测本身的正确以外,还要加上一个"伪首部",伪首部中包含IP相关的地址信息,以及一些特殊字符,换句话说检验和的时候是同时检验IP分组和UDP/TCP数据报文两个部分.
(两个快乐一次满足)
UDP其实没啥东西,综上所述就这么多,接下来我们将主要聚焦于对于TCP的讲解
2.2:面向链接的TCP
这个东西真的很重要,因此内容也比上面的多很多,关于基础部分我们将在2.2全部阐述清除,至于一些控制和有关的算法(流量控制, 拥塞控制, 超时重传)将会在第三个板块中进行解析.
内容不少,都坚持到这里了,来个简单的赞呗.
和UDP不用,TCP实现的是稳定的,可信赖的数据传输,这就要求TCP建立一个完善的链接和释放链接的机制,分别被称之为三次握手和四次挥手,是很重要的内容.
另外和UDP不同,TCP只允许双方之间建立一个一对一的链接和数据通信,因此不允许类似UDP的广播机制,接下来将针对数据报文的处理,首部格式,可靠传输的支持三个方面来进行解析.
2.2.1:TCP对于报文的处理
简单来说,TCP对于报文的处理被我们称之为:"面向字节的处理",可能是由于TCP支持的是稳定的可靠传输,所以可以放心的把数据分段,又或者是因果倒转,总之不重要,TCP是可以把上层发来的应用层报文的结构无视掉,直接转化为字节的形式进行发送.
2.2.2:TCP报文段的首部:
这里把顺序稍微倒转一下,先解释一下TCP报文段的首部,因为有些东西实在是太重要了.....比如ACK之类的
TCP数据头部的长度和IPv4很想, 甚至一些实现思路都很像, 为20字节的固定长度+40字节的扩展首部组成了TCP数据报文.接下来将会详细解释有关于这个头部的内容
源端口和目的端口:这俩不用解释,用来在目标主机上找到特定的进程,交付或者接收服务:
序号:序号用来指定和说明,自己当前传递的是从哪个编号开始的,或者说指出当前所负载数据的第一个字节的编号,发送数据的时候和窗口相结合,确定发送数据的范围.由于TCP是一个双工通信,因此可以说不存在一个完全的发送方和一个完全的发出方.
而序号的存在,意为"我发送了什么数据",或者说"我发送的数据开头是什么",至于为什么要提到没有完全的输入或者输出,因为和后面的确认序号以及握手相关算法有关
确认号(ACK):确认号即可以用来说明,自己接收到了什么数据,也可以说明"自己接下来想要什么数据". 举个例子 , 当返回的报文中 , ACK的数值为301 , 则代表接收方已经确认接收到了0-300编号的字节, 换个解读方式就是"接下来想要301开始的字节"
数据偏移字段:数据偏移字段占四个比特位置,用来指出TCP报文段的数据载荷的起始部分,距离TCP头部的距离......这个解释比较抽象对吧....其实就是用这样一个变量直接指出了头部的大小,单位四个字节
保留字段: 占六个比特 , 全是0 , 据我所知没用
窗口字段: 窗口字段的作用就是用来指出发送本报文段的一方的接收窗口大小 , 也就是"告诉你我的载荷能力是多少"
检验和字段:和UDP中差不多的伪头部,连着IP一起验证了,这里就不多赘述了
一些标志位:这些标志位各占据一个比特,针对考试来说应该不算是很重要,因此在这里简单解释一下了.
- 同步标志位SYN: 用于双方建立链接,同步标志位为1的时候,如果ACK为0,则是一个请求连接报文段. 如果ACK为1的时候,则是一个链接相应报文段.
- 终止标志位FIN:终止标志位为1的时候代表数据已经完毕,可以释放TCP链接了
- 复位标志位RST:用于复位TCP链接
- 推送标志位PSH:一般来说,每个报文段在填充其数据载荷的时候,都需要填充一定的数据,才能封装成一个报文段,这一点有点类似我们在学习网络编程的时候"缓冲区"的概念,因此会造成一点延时,如果想要立刻发送,就把PSH设置为1,这个数据包就会立刻进行发送. 而对于接收方来说 , PSH就相当于一个加急引号,会尽快将其交付给应用进程,而不是手机足够多的数据才进行交付
- 紧急标志位URG:1有效,0无效,和紧急指针字段结合使用
- 紧急指针字段:对于发送方来说,如果由很紧急的数据部分,会将其放入数据载荷的前段,而紧急指针就是用来指明哪些是紧急字段,在紧急指针之后的则是普通字段. 而对于接收方来说,会根据紧急指针字段,将数据载荷中的紧急字段直接交付,而不是在缓存中等待.
选项字段和填充字段:一些可选部分,组成了0-40字节的可变长度部分
2.2.3:TCP对于数据可靠性的支持
这里就不能用不等式了,TCP关于数据可靠性的支持既包括链接内容,也包括对于重传的处理,发送接收窗口的维护,另外关于缓存,拥塞,重传,超时等等处理将会放在第三部分进行解决,稍安勿躁...
.
2.2.3.1:TCP建立连接(三次握手)
TCP链接的建立主要解决三个问题:TCP能够感知对方的存在,能够协商参数,并且保证双方能传递实体资源.每一次发送请求和确认报到对方的过程我们称之为"握手",所以称之为三次握手:
在握手之前,双方都处在一个关闭状态,并且在开始之前,服务器端是进入了一个"监听"状态.
第一次握手:客户向服务器发送一个TCP链接请求报文,发送以后客户进入"同步已发送状态",等待客户端返回的TCP链接请求确认报文.
第二次握手:服务器接收到TCP链接请求报文以后,自身由监听状态改为"同步已接受状态", 并且向客户端发送一个TCP链接请求确认报文.
第三次握手:客户端接收这个TCP链接请求确认报文以后,自身进入"链接确认状态".并且向服务器发送一个普通TCP确认报文段,服务器接收到这个报文段以后,自身状态也会从"同步已接收"转化为"链接确认"
如图所示:
当然其实对于我们来说,这个报文段可以抽象一点,举个实际生活的案例:
为什么一定要做三次握手,这是从离散数学或者说实际生活中得到的例子, 保证双方能确认彼此的存在和确认对方知道自己的存在.
从实际工程的角度来说,三次握手是为了防止已经失效的TCP请求链接报文发生重传导致混乱,举个例子,如果只有两次握手:
这个状态下,两次握手以后,就能直接进入数据确认状态. 如果在结束以后重新接收到了重传的请求, 服务器会重新进入一个对于链接的确认状态,重新准备自己这边的链接状态(因为在两次握手下,只要接收到请求就可以进入链接状态),造成了一定的浪费.
2.2.3.2:TCP释放链接(四次挥手)
四次挥手指的是在完成数据传输以后,TCP协议双方手动释放掉数据链接的过程,类似上述的描述,我们称之为四次挥手,也就是有四次的报文交互:
(1)第一次挥手:在链接已经创建完成的情况下,客户主动提出取消链接,发送一个TCP链接释放报文,自身进入终止等待1状态.
(2)第二次挥手:服务器端接收到这个TCP链接释放报文以后,自身进入关闭等待状态,在此期间,服务器需要通知自身的进程关闭,并且在这个阶段里数据是仍然有所传输的(换句话说进程仍在工作).并且向客户端发送一个普通TCP确认报文,客户端接收到这个报文以后,进入停止等待2状态.
(3)第三次挥手:服务器完成自身关闭进程的准备工作以后,就停止数据传输和关闭应用进程,并且向用户端发送一个TCP链接释放报文 , 自身进入最终确认状态.
(4)第四次挥手:客户端接收到TCP链接释放报文,就发送一个TCP确认报文段,同时自身进入时间等待状态.服务器接收到这个释放报文以后,就关闭.而客户端会在等待2MSL以后,也进入自身的关闭状态.
如图所示:
至于为什么要四次挥手,这里比较难用逻辑或者离散数学的东西进行解释了,这里就一种特殊情况解释一下时间等待机制是在做什么:
时间等待机制指的是,为了防止最后通知服务器的TCP链接释放报文被忽视掉,例如第四次挥手,如果这个TCP链接释放报文丢失了,如图所示
那么服务器端就接收不到停止指令,这个时候服务器收不到应答,,就会持续发送请求报文
但是由于没有等待时间,就会导致再往后就无法处理这个关闭请求报文了,因此造成错误
所以四次握手在实际上的作用就是:确保TCP服务进程能够收到最后一个TCP确认报文而进入关闭状态
2.2.3.3: TCP保活计时器
基于链接已经建立的情况下,我们仍然会发生一些特殊情况,这个时候就不能通过握手挥手等等方式来进行链接.
因此此时TCP需要某种手段,知道当前应该单方面关闭链接了 , 使用保活计时器来解决
在数据链接的过程中: TCP服务器进程维护一个保活计时器,每次收到数据,就重置计时器. 如果在规定周期内没有收到服务器信息, 就每隔75秒发送一个探测报文段, 如果连续发送十个探测报文段以后仍然没有收到回复,就会单方面关闭这个链接.
3.TCP实现的一些可靠传输的支持以及算法
其实在上面的部分,我们已经详细阐述了什么是TCP,并且解释了TCP的链接支持,这个连接机制保证了数据可以放心传递,但是因为传递数据本身是一个很复杂的问题,所以一时半会也说不清楚.....
在这里详细阐述一下TCP实现的一些支持手段,流量控制,拥塞控制,重传机制等等,这些机制保证了TCP能提供可靠传输服务
3.1:流量控制
流量控制之前,我们需要回忆一下之前讲过的一个知识点就是"确认号"/"窗口字段",这个两个字段发挥作用的地方 , 就是在作为请求报文, 指明了发送方需要的数据从何处开始,以及可以接收多少数据.
有的时候,因为发送方发送数据过快,就导致接收方的接收有一定限制,进而产生一些溢出情况.而控制流量的基本方法,就是让接收方根据自身情况,来确定请求数据量的多少.进而限制发送方的发送速率
而TCP实现流量控制的操作,就是在发送端维护一个滑动发送窗口,根据接收端的确认报文来调整窗口的大小,和窗口头部的位置.这一点和前面的回退n帧重传很像.
我们以这样一个链接建立以后进行举例说明:
我们将称之为A发送方,B发送方,A维护一个发送窗口,默认发送窗口为400
在发送窗口中的数据,会按照顺序一个一个的进行发送,我们先假设其中发生了一个丢失的情况
正好此时,B发送回来一个确认报文,确认号为201,意为接收到了0-200的数据,并且接收窗口rwnd为300.此时根据这个情况,发送方要做两个事情,首先是调整窗口的大小,将窗口大小调整为300,然后根据确认号,将发送窗口头部移动到201. 如图所示
然后继续按照之前的顺序传递,301-400,401-500两段数据,这个时候因为到达了窗口的尽头没所以就不能再次发送数据了, 但是那时因为201丢失,这个时候触发了超时重传机制,重传旧数据201-300.
传出以后,返回一个确认数据报,这个时候重新进行了调整,窗口大小为100,以此类推,这就是流量控制的大致过程
当rwnd=0的时候,意思就是不再接收数据了,也就是所谓的0窗口报文段,作为发送数据的一个暂时中止.但是如果紧随其后,发送方又有了一些数据空间,这个时候怎么办呢?
这个时候就需要一个名为"持续计时器"和"零窗口探测报文段" ,
当主机A收到一个零窗口报文段的时候,会启动一个计时器,计时器结束以后会发送一个0窗口探测报文段,这个时候主机B就会返回自身的缓存状态,也就是窗口数据报文.
3.2: 拥塞控制
对于点到点的数据传输来说,当我们将目光放在端点上,主要的目标考虑必然是对于流量的发送和接收限制. 但是将目光放在整体上,网络资源本身也是一个需要考虑的点. 流量控制的任务是保证发送方不会持续地以超过接收方接收能力的速率发送数据, 而是拥塞控制的任务,则是避免过多的数据注入到网络中,对网络本身产生较大的载荷,进而影响传输.
网路资源包括:链路容量, 缓存,交换机,路由器等等,甚至是线路的数目也算是网络资源的一部分. 为了不让这些资源被过度使用,我们在这里引入了拥塞控制机制.
首先如图所示: 拥塞的情况
如果输入网络的负载无限制增大,最终的后果就是吞吐量变成0,这就是死锁,因此我们需要对拥塞的情况做出一点控制.关于拥塞的处理有很多思想和实现方向,在这里我们不做解释,仅仅处理普通的算法.
首先我们需要明确三个前提情况,方便我们对后续的情况进行简单的阐述
接下来我们将会按照结合使用的例子 , 分别讲解如下四个控制以及回退的手段
当然在之前,仍然要提供几个定义内容:
1. cwnd: 拥塞窗口,由发送方进行维护的状态变量,Cwnd的原则是,如果没有发生拥塞,就大一些,如果发生了拥塞就小一些. 一般初始数值被定义为1
2. swnd:发送窗口,理论上这个是需要我们进行单独维护的内容,但是实际上出于延时具体算法的考虑,我们在这里直接摆正cwnd=swnd
3. ssthresh:慢开始门限/阈值,超过整个阈值,则会调整计算方式,比如讲慢开始调整为拥塞避免, 初始数值仍然由发送方进行维护
3.2.1:慢开始和拥塞避免
慢开始算法的意义是 :将初始窗口大小设置为1,每次收到一个新的确认报文的时候,就把拥塞窗口的数值*2.
拥塞避免:当cwnd的数值大于ssthresh的时候 , 将慢开始算法的指数增加修改为线性增加.
当发生拥塞的时候 , 设定当时的cwnd为x , 则这个时候就需要对ssthresh进行调整 , cwnd变为1, ssthresh设定为发生拥塞时候cwnd的一半,即设定为x/2 .
话不多说,直接上图
3.2.2:快重传和快恢复
话不多说,还是直接上图
但是这里的图上我们可以看到一个东西"收到三个重复确认",其实我们大多数应该能知道这是因为丢失重传 , 但是为什么要有这个控制? 这也就是为什么要放在这里展开说,如何判断拥塞,以及为什么在原本的基础上新增这两个算法(其实这四个算法是连用的,而不是两两分用)
我们目前的理解,超时重传代表了网络资源的严重不足,但是有时候个别包的丢失也会导致超时重传,这种如果被判断为拥塞, 那么就会严重浪费一些资源.
而快重传,实现的就是让发送方尽早知道个别报文段的丢失,尽早重传,而不是等着计时器归零再超时重传, 一旦发送方收到了三个连续,对已经确认报文段的重复确认,那么就代表要对相应的报文段进行立刻重传.
而与之配合的,一旦发生快重传,仍然要进行名为"快恢复"的调整算法,这个东西和拥塞避免很像,但是调整的数值略微不同: 当发生快重传的时候 , 设定当时的cwnd为x , 则这个时候就需要对ssthresh进行调整 , cwnd变为原来的一半, ssthresh设定为发生拥塞时候cwnd的一半,即设定为x/2 .
3.2.3:拥塞是如何判断的
拥塞指的是网络资源的不足而产生的问题,在本博客中,我们主要认为有两种方式来判断是否发生了拥塞.
显示反馈算法: 由发生拥塞的节点直接向源点提供拥塞相关的信息
隐式反馈算法: 通过对于网络行为的观察,来判断是否发生了阻塞
互联网中主要使用隐式反馈算法来判断是否发生了拥塞, 在上述的两个算法中, 实现的拥塞判断就是"重传机制",不过这个会有很多很多的问题,比如快恢复算法就是针对误判进行的修正
3.3: 可靠传输/滑动窗口
TCP实现可靠传输时通过滑动窗口机制
其实这里甚至不用多说,和选择重传协议是几乎完全一致的,可以去复习一下数据链路层的选择重传协议
3.4:超时重传
超时重传的实现其实肥肠简单,例如图中这种情况
应答之间超出了我们的等待时间"RTO"就会进行重传, 过大或者过小都会引发很多问题,一个正确的处理方式应该是略大于每次的往返时间
但是问题在于,每次重传带来的RTTX都是不一样的,这就需要我们的某个迭代算法来计算合适的RTO超时重传时间.
在这里我们准备两个量:每次测得的RTT样本RTTS
以及平均差RTTD,根据这两个变量的每次迭代,我们就能计算出一个合适的RTO
RTTS的计算需要一个平滑的过度,这里我们引入一个概率a
其中第一个RTTD,我们赋值为RTTD=RTT1
至于RTTD的计算同样很复杂,和上面的例子差不多,这里我们将计算公式直接截出来
以上其实就是超时重传的全部内容了,但是我们在这里肯定会遇到一个问题
如果再测量RTT的时候,发生了重传,导致时间测量不准...如图所示
两种类型,无法确定到底哪个是可行的,因此一开始选择的机制是"对于超时重传,统统不计算RTT",这就是Karn算法.
但是由于每次迭代都要重新更新RTO,遇到超时重传比较频繁的情况, 一直会发生无法更新RTO的情况,因此Karn算法有一个修正:"报文每次发生重传,就把RTO增大一倍"
3.5:缓存和窗口的关系
在之前我们聊过不少有关发送窗口和发出窗口的例子,也知道只有在窗口内的才能进行发送和确认,而经过窗口的是确定确认过的字段.
但是我们再上面似乎混淆了缓存和窗口的概念,虽然这个东西就像路由表和转发表一样,混淆了也不是什么大事,但是说明一下也是好事
对于发送窗口和发送缓存来说: 首先需要将进程发送的数据添加到缓存中,只有在缓存中的数据,才能被窗口所扫描
对于接收窗口和接收缓存来说: 需要先由窗口扫描确认接收,才能放入缓存中
相关文章:

[计算机网络]运输层概述
虽然我自己也不知道写在前面和前言有什么区别..... 这个系列其实是针对<深入浅出计算机网络>的简单总结,加入了一点个人的理解和浅薄见识,如果您有一些更好的意见和见解,欢迎随时协助我改正,感激不尽啦. 最近心态平和了不少, 和过去也完全做了个割舍吧,既然痛苦和压力的…...

【分布式】分布式事务及其解决方案
目录 一、分布式事务二、分布式事务的解决方案1. 全局事务(1)DTP模型(2) 两阶段提交协议(2PC)原理二阶段提交的缺点 (3)三阶段提交协议(3PC)原理 2. 基于可靠…...

【文末送书】机器学习高级实践
2023年初是人工智能爆发的里程碑式的重要阶段,以OpenAI研发的GPT为代表的大模型大行其道,NLP领域的ChatGPT模型火爆一时,引发了全民热议。而最新更新的GPT-4更是实现了大型多模态模型的飞跃式提升,它能够同时接受图像和文本的输入…...

吉他初学者学习网站搭建系列(1)——目录
文章目录 背景文章目录功能网站地址网站展示展望 背景 这个系列是对我最近周末搭建的吉他工具类平台YUERGS的总结。我个人业余爱好是自学吉他,我会在这个平台中动手集成我认为很有帮助的一些工具,来提升我的吉他水平和音乐素养,希望也可以帮…...

qgis添加arcgis的mapserver
左侧浏览器-ArcGIS地图服务器-右键-新建连接 Folder: / 展开-双击图层即可...

关于「光学神经网络」的一切:理论、应用与发展
/目录/ 一、线性运算的光学实现 1.1. 光学矩阵乘法器 1.2. 光的衍射实现线性运行 1.3. 基于Rayleigh-Sommerfeld方程的实现方法 1.4. 基于傅立叶变换的实现 1.5. 通过光干涉实现线性操作 1.6. 光的散射实现线性运行 1.7. 波分复用(WDM)实现线性运…...
【HarmonyOS】ArkTS开发@Styles装饰器和@Extend装饰器详解
文章目录 HarmonyOS详解ArkTS详解ArkTS装饰器深度解析:@Styles、@Extend、和stateStyles@Styles装饰器:优雅的组件样式定义与重用@Extend装饰器:扩展原生组件样式的利器stateStyles:多态样式的应用示例场景:装饰器的联合使用进阶应用:动态样式与交互最佳实践:样式的组织…...
Android修行手册-一个滑动旋转的弧形菜单
Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列...
数组名的理解
1.引入 int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,⽽且是数组⾸元素的地址,我们来做个测试。 #include <stdio.…...

Robots 元标签与 X-Robots 标签
Robots Meta Tag 和 X-Robots-Tag 是两个常用的 HTML 标签,它们对观察机动爬虫和其他网络机器人很有启发性。这些标签可以控制您的网页如何被记录和显示。 什么是机器人元标记? 机器人元标记是一个 HTML 标签,它提供信息来查看电机爬虫和其…...

【数据结构实验】排序(二)希尔排序算法的详细介绍与性能分析
文章目录 1. 引言2. 希尔排序算法原理2.1 示例说明2.2 时间复杂性分析 3. 实验内容3.1 实验题目(一)输入要求(二)输出要求 3.2 算法实现3.3 代码解析3.4 实验结果 4. 实验结论 1. 引言 排序算法在计算机科学中扮演着至关重要的角色…...

微信小程序开发者工具] ? Enable IDE Service (y/N) ESC[27DESC[27C
在HBuilder运行微信小程序开发者工具报错 如何解决 打开微信小程序开发者工具打开设置--->安全设置--->服务器端口选择打开就可以啦...
【数据结构】E : 货币套汇(图路径)
E : 货币套汇(图路径) Description 套汇是指利用货币汇兑率的差异将一个单位的某种货币转换为大于一个单位的同种货币。例如,假定1 美元可以买0.7 英镑,1 英镑可以买9.5 法郎,1法郎可以买到0.16美元。通过货币兑换&a…...
图书管理系统源码,图书管理系统开发,图书借阅系统源码SqlHelper数据库访问操作方法简述
SqlHelper 是封装了数据库操作方法的类库,使用它我们可以链接数据库操作数据库表数据增删改查,其中主要SqlConnection ,ExecuteNonQuery,ExecuteScalar,ExecuteDataTable四个主要方法SqlConnection负责根据访问配置文件web.config中connstr链接数据库字符串去打开数据库,…...
富文本编辑器的实现与回显
文本编辑器实现-wangeditor 写之前记得安装wangeditor插件,到时候报错别赖我 import “wangeditor/editor/dist/css/style.css”; import { Editor, Toolbar } from “wangeditor/editor-for-vue”; defineOptions({name: "BaseEditor" });const mode …...

探索亚马逊云科技云存储服务的性能
文章作者:Libai 引言 随着企业越来越多地依赖云存储解决方案,确保存储性能的最佳状态变得至关重要。在本文中,我们将探讨在亚马逊云科技云存储服务上进行存储性能基准测试的重要性,以及如何帮助企业做出资源分配和优化的明智决策…...

初出茅庐的小李博客之C语言必备知识共用体
C语言必备知识共用体 共用体是一种构造数据类型,有时候也称之为联合体。 它的用途: 使几个不同类型的变量共占一段内存。 共用体举例 union 共用体名 { 类型标识符 成员名;类型标识符 成员名; };union data //共用体名字是data{ int i; …...

vue3+elementPlus之侧边菜单栏功能
选择默认的颜色,将代码拷贝至<el-aside>模块中 稍微把不需要的修改一下。 <template><div class"common-layout"><el-container><el-header class"homeHeader"><div class"headerTitle">Devops…...

阿里云服务器安装mysql数据库之后无法远程连接
目录 一、mysql安装完成后直接远程远程连接阿里云服务器上的MySQL会报下述错误: 1、修改root用户的host 为% 登录MySQL 后 执行 2、修改完成后执行 3、退出mysql 重启mysql服务 exit; 4、修改完成后需要设置阿里云的安全规则。 二、dbaver测试链…...

如何把自己银行卡里的钱转账充值到自己支付宝上?
原文来源:https://www.caochai.com/article-4524.html 支付宝余额是支付宝核心功能之一,主要用于网购支付、线下支付、转账等场景。用户可以将银行卡、余额宝等资金转入或转出至支付宝余额,实现快速转账和支付。 如何把自己银行卡里的钱转账…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...

相关类相关的可视化图像总结
目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系,可直观判断线性相关、非线性相关或无相关关系,点的分布密…...
八、【ESP32开发全栈指南:UDP客户端】
1. 环境准备 安装ESP-IDF v4.4 (官方指南)确保Python 3.7 和Git已安装 2. 创建项目 idf.py create-project udp_client cd udp_client3. 完整优化代码 (main/main.c) #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h&…...

Digital IC Design Flow
Flow介绍 1.设计规格 架构师根据市场需求制作算法模型(Algorithm emulation)及芯片架构(Chip architecture),确定芯片设计规格书(Chip design specification) 原型验证 原型验证(Prototype Validation)通常位于产品开发流程的前期阶段,主要是在设计和开发的初步阶…...