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

【网络】数据链路层——MAC帧协议 | ARP协议

🐱作者:一只大喵咪1201
🐱专栏:《网络》
🔥格言:你只管努力,剩下的交给时间!
图

来到数据链路层后,完整的数据被叫做数据帧,习惯上称之为MAC帧。

MAC帧协议 | ARP协议

  • 🦺以太网协议
    • 👑认识MAC地址
    • 👑协议报头
  • 🦺局域网转发原理
    • 👑认识MTU
  • 🦺ARP协议
    • 👑协议格式
    • 👑ARP缓存表
  • 🦺回顾整个协议栈
  • 🦺总结

🦺以太网协议

网络层的IP协议并不是将数据报直接发到了网络中,而是将数据报继续向下交付,给到了数据链路层。

图
如上图所示,每一个红色的圈就是一个局域网,假设现在主机A要将数据发送到主机D,这个数据要经过多个局域网,要一跳一跳到达主机D。

  • 所以说网络传输的本质,就是多个局域网(子网)转发的结果!!!

数据链路层负责数据在一个局域网中的传送,我们主要研究数据链路层的以太网协议,也被叫做MAC帧协议

一个局域网中有多台主机,这些主机之间通过以太网等网络连接,进而可以直接通信。

图
如上图所示便是局域网通信示意图,多台主机处于一个局域网中,通过以太网连接,主机名称从MAC1~MAC7,其中MAC1是该局域网的入口路由器,也可以看成是一台主机,因为它也有网卡,具有网络通信的能力。

  • “以太网” 不是一种具体的网络,而是一种技术标准,既包含了数据链路层的内容,也包含了一些物理层的内容。
  • 以太网规定了网络拓扑结构,访问控制方式,传输速率等,而且网线必须使用双绞线,传输速率有10M, 100M, 1000M等。
  • 以太网是当前应用最广泛的局域网技术,和以太网并列的还有令牌环网,无线LAN等。

不管是什么类型的网络,都是用来组成局域网进行网络通信的。

👑认识MAC地址

每台主机都至少有一张网卡,每个网卡都有一个唯一的序列号sn,这个序列号被叫做MAC地址,该地址全球范围内具有唯一性。

  • MAC地址是一个6字节的十六进制序列号,形如1A:2B:3C:4D:5E:6F

我们不是已经有了IP地址了,为什么还要有MAC地址呢?

  • IP地址描述的是整个数据传送过程中的起点和终点。
  • MAC地址描述的是数据传送过程中,每一跳(一个区间)的起点和终点。

IP地址指引着方向,MAC地址则是投石问路,一步一步来,比如本喵现在要从北京到上海,路途中会经过石家庄,南京,苏州…等地,这个过程中,上海就相当于IP地址,途中经过的城市就相当于MAC地址。

具体在网络中,IP地址就是目标主机,MAC地址就是两个相连路由器,只有一跳一跳经过多个路由器,数据才能被送到目标主机。

  • MAC地址严格来说并不需要全球唯一,只需要保证同一个局域网中的唯一性即可。

但是制造厂商在制造的时候将其设置成了全球唯一,主要是因为网卡制造厂商非常多,无法保证不同厂商制造的网卡不会出现在同一个局域网中,所以就直接一刀切了,让MAC地址成为全球唯一。

  • 不同厂商可用的MAC地址参照了子网划分的方式,保证不同厂商之间的MAC地址不会重复。

👑协议报头

图
如上图所示MAC帧协议格式,与之前的TCP/UDP以及IP协议相比,简单了许多,报头只有三个字段:

  • 源地址和目的地址是指网卡的硬件地址(MAC地址),长度是48位,是在网卡出厂时固化的,不可以修改。
  • 帧协议类型字段有三种值,分别对应IP、ARP、RARP,也就是向上交付时要交付的协议类型。

图
如上图,0800表示要分用给IP协议,0806表示要分用给ARP协议,8035表示要交给RARP协议,后两者协议本喵在后面会详细介绍。

  • 帧末尾是CRC校验码,用来校验数据是否正确,和校验和是一样的作用。

MAC帧协议同样要面临解包和分用的问题,它非常的简单粗暴,采用的是定长报头的方式。

目的MAC地址是6字节大小,源MAC地址也是6字节大小,帧协议协议类型字段2字节大小,末尾校验和CRC是4字节大小,有效载荷的大小是46~1500字节,后面本喵会将原因。

所以在解包的时候,从整个数据帧读取前14个字节,然后再从最后读取4个字节,剩下的就是有效载荷,如此就完成了解包过程。

在分用的时候,根据帧协议类型交给对应的上层协议即可,如0800就交给网络层的IP协议去处理有效载荷。

🦺局域网转发原理

图
如上图所示,主机MAC1发送了一个数据帧给MAC7,当数据从IP层交给数据链路层后,数据链路层给数据报加上了报头,成为了数据帧,然后发送出去,这次是真正的发送出去,数据帧在网线中跑。

而局域网中存在多台主机,这些主机都和以太网相连,都能够看到以太网,故而也能看到以太网中跑的数据。

  • 网络通信本质上就是进程间通信,而网络就是临界资源。

所以局域网中的所有主机都唔那个收到主机MAC1发送的数据,每台主机在收到数据后,数据链路层会对比数据帧报头中的目的MAC地址,如果和自己的MAC地址相同,则进行解包分用交给下一层。

如果数据帧报头中的目的MAC地址和自己的MAC地址不符,那么直接在数据链路层就丢弃该数据,上层根本不知道曾经有过这个数据。


上图中,主机MAC7在数据链路层对比发现报头中的目的MAC地址和自己的MAC地址相同,所以进行解包分用交付给网络层,然后再逐层交付到应用层。

应用层在处理完以后将响应封装并向下交付,最终交付给数据链路层,此时数据链路层将MAC1作为目的地址,将MAC7作为源地址,打包成数据帧后发送到以太网中,数据帧如下图:

图

同样的,以太网中的所有主机的数据链路层都能收到MAC7的响应数据,只是发现目的地址和自己不符丢弃了,最终只有主机MAC1接收了该响应,并解包分用给上层。

  • 既然主机MAC1可以发送数据,那么其他主机也可以发送数据。

而以太网又是一个共享资源,多台主机同时向以太网中发送数据也会导致"数据不一致问题",体现在以太网中就是数据碰撞。

  • 数据在以太网中是以光电信号的形式传输的,也就是一段波。
  • 当不同的光电信号发生碰撞时,就会产生波的叠加或者衰减,导致原本的光电信号发生变化,进而导致数据传输出错。

而令牌环网就是为了解决数据碰撞产生的,在局域网中存在一张令牌,只有持有令牌的主机才能向网络中发生数据,就像我们多线程中的互斥锁一样。

但是主流的网络仍然是以太网,以太网采用碰撞检测和碰撞避免的算法来避免碰撞带来的影响。

假设主机MAC1发送了一个数据帧,主机MAC7也发送了一个数据帧,互相发送给对方,这两个数据帧在以太网中发生了碰撞。

  • 主机MAC1收到主机MAC7发送的数据后,发现CRC校验值和主机MAC7封装数据帧时的值不一样。
  • 说明该数据发生了碰撞,而主机MAC1自己刚刚也发生了一个数据帧,所以为了避免再次碰撞,主机MAC1等待一段时间后再重发刚刚的数据。
  • 主机MAC7采用同样的策略。

这就是碰撞检测和碰撞避免算法的大概原理,有兴趣的小伙伴可以自行研究。

如果此时主机MAC2不断向局域网中发送垃圾数据,并且不执行碰撞检测和碰撞避免,那么就会导致其他主机无法发送数据,一直处于碰撞检测和碰撞避免的状态。

交换机:

图
如上图所示,一个局域网中存在很多天主机,此时向网络中发送数据的主机也就多了起来,进而导致发生碰撞的概率增加。只要主机足够多,概率性事件就会成为必然事件。

所以在比较大的局域网中,会有交换机的存在,如上图蓝色框所示,它将局域网分成了两部分,交换机左边是一部分,右边是一部分。

假设左边的主机MAC1向右边的主机MAC100发生数据,这个数据在局域网中传送时,会先经过交换机,由交换机转发给主机MAC100

如果主机MAC1向主机MAC2发生数据,则不通过交换机转发,直接发送,同理交换机右边也是一样的。

当主机MAC1向主机MAC100发送数据时,数据帧在左边部分发生了碰撞,那么当数据经过交换机时,交换机便不再转发这个数据,而是直接丢弃。

  • 交换机能识别局部碰撞,对碰撞数据不做转发。
  • 交换机将局域网划分成了多个碰撞域,从而减少了局域网中的数据碰撞。
  • 通常情况下局域网都不会很大。

👑认识MTU

对于以太网来说,既然会存在碰撞,那么发生的数据帧是长了好还是短了好呢?

太长和太短都不行,太短会导致数据帧无法校验,因为CRC校验是需要数据帧中有一定数量的有效载荷的,所以MAC帧协议规定,有效载荷的长度要大于等于46字节。如果最终交付到数据链路层的有效载荷太小,小于46字节,MAC帧协议会在后面补充到46字节。

如果太长的话,数据在以太网中传输的时间就会变长,从而增加了数据碰撞的概率,也不合适,所以MAC帧协议规定有效载荷的最大值是1500字节,也被叫做以太网的最大传输单元(MTU)。

  • 不同的网络类型有不同的MTU。
  • 如果IP层的数据报大于MTU了,则需要分片,然后再交给数据链路层。
  • 不同数据链路层的标志MTU也是不同的。

MAC帧的有效载荷在46~1500字节的范围内也会发生碰撞啊,这样规定貌似并没有解决这个问题。

  • 数据在以太网中是以光电信号的形式传输的,只要有效载荷在规定范围内,那么碰撞的概率就很小。
  • 光传送速度是非常快的,我们要相信光的力量。

MTU对TCP协议的影响:

由于数据链路层MTU的限制, 对于较大的IP数据包要进行分包,将较大的IP包分成多个小包,并给每个小包打上标签,每个小包IP协议头的16位标识(id)都是相同的。

每个小包的IP协议头的3位标志字段中,第2位置为0,表示允许分片, 第3位是更多分片标志位,在上篇文章中本喵有详细介绍。

到达对端时再将这些小包按顺序重组,拼装到一起返回给传输层,一旦这些小包中任意一个小包丢失,接收端的重组就会失败。

但是IP层不会负责重新传输数据,是由TCP负责的,当TCP没有收到对方的确认应答时就会触发超时重传。

图
MTU对IP协议的影响就向上图快递类型对发货量的影响。发货人在东京使用的是FDDI快递,该快递一次运输的快递上限是4200kg,发送方在IP报头中填好IP地址等内容后交给快递公司发往仓敷。

快递首先从东京发往了大阪,快递重量是4200kg,在大版换成了以太网快递公司,该快递一次运输的快递上限是1400kg,所以原本4200kg的快递需要分成三趟去发。

最终在仓敷的收件人收到的快递是3个1400kg的包裹,将这几个包裹组装后得到一个4200kg的包裹。


这个过程中,FDDI和以太网是两个不同类型的局域网,所以MTU也不同,将快递看成是数据,从东京到仓敷的过程需要跨越两个局域网,要通过两个局域网的转发。图

如上图网络传输示意图中,从东京到大版的局域网中,MTU是4200,从大版到到仓敷的局域网中,MTU是1400,所以数据原本4200的数据到了大版路由器以后,被拆分成了3个1400的数据发往仓敷。

  • 路由器有数据链路层和网络层俩层,网络层是主要就是IP协议,能够屏蔽网络底层的差异。
  • 路由器有将IP数据报进行分片的能力。

至于具体是如何分片和组装的,感兴趣的小伙伴可以去看本喵的上篇文章。从上面这个例子中可以看出MTU的大小决定着IP协议是否进行分片,不同局域网有着不同的MTU,而路由器可以针对不同MTU采取相应的对策。

MTU对DUP的影响:

图
如上图所示,发送端主机向MTU为4352的FDDI局域网中发送数据,该数据帧中,包含4324字节的UDP有效载荷,8字节的UDP报头,20字节的IP报头。

当局域网中的路由器接收到该数据帧后,发现接收主机所在的局域网为MTU = 1500的以太网,所以在路由器中将IP数据报进行分片,如上图所示,分成了三片,然后发送给接收主机。

接收主机接收到以后,进行组装,然后将完整的数据交付给上层。

  • 一旦UDP携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)),那么就会在网络层分成多个IP数据报。
  • 这多个IP数据报有任意一个丢失,都会引起接收端网络层重组失败 而且UDP没有重传机制,这就意味着这个数据丢了。
  • 如果UDP数据报在网络层被分片,整个数据被丢失的概率就大大增加了。

MTU对UDP的影响和TCP类似,只是对于UDP丢包时的影响更加严重。

MTU对TCP协议的影响:

  • TCP的一个数据报也不能无限大,还是受制于MTU,TCP的单个数据报有效载荷的最大消息长度,称为MSS(Max Segment Size)。
  • TCP在建立连接的过程中, 通信双方会进行MSS协商,最理想的情况下,MSS的值正好是在IP不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的MTU)。
  • 双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值,然后双方得知对方的MSS值之后,选择较小的作为最终MSS。
  • MSS的值就是在TCP首部的40字节变长选项中(kind=2)。

图
如上图所示便是MSSMTU之间的关系,由于IP报头和TCP报头长度固定,所以MTU的大小直接关系到MSS的大小。


图
如上图所示,使用ifconfig可以看到当前机器所在局域网的MTU,本喵的Linux机器所在局域网的MTU = 1500字节。

🦺ARP协议

图
如上图所示,主机A向主机B发送数据,数据一跳一跳经过多个局域网转发,最终到达了主机B所在的局域网。

  • 主机将数据交付给下一跳时,下一跳可能是主机,也可能是路由器节点。
  • 前提是该数据帧一定被网络层路由过,所以才能知道下一跳要去哪里。

当数据帧第一次到达主机B所在的局域网入口路由器时,路由器就迷茫了,路由器的数据链路层解包分用后,只能从网络层中得到主机B的IP地址,但是在局域网中是通过MAC地址来识别主机的,但是路由器并不知道主机B的MAC地址。

  • 要有一个过程,让路由器设备认识主机B,获取主机B的MAC地址。

此时就用到了ARP协议,ARP不是一个单纯的数据链路层的协议,而是一个介于数据链路层和网络层之间的协议:

图

如上图所示,ARP协议处于数据链路层,MAC帧协议在分用的时候,可以将有效载荷分用给ARP协议,PARP协议,还有网络层的IP协议。

图
前面本喵讲解MAC帧协议格式的时候,报头中的协议类型字段,0800表示IP协议,0806表示ARP协议,8035表示RARP协议。

👑协议格式

图
如上图所示便是ARP协议的格式,它的长度是固定28字节,且没有有效载荷。

  • 硬件类型指链路层网络类型,1为以太网,通常情况下都是1,相当于一个固定参数。
  • 协议类型指要转换的地址类型,0x0800为IP地址,通常情况下都是这个值,也相当于一个固定参数。
  • 硬件地址长度对于以太网地址为6字节,也相当于是一个固定参数。
  • 协议地址长度对于和IP地址为4字节,也相当于是一个固定参数。
  • op字段为1表示ARP请求,op字段为2表示ARP应答。
  • 发送端以太网地址和发送端IP地址,以及目的以太网地址和目的IP地址相信大家一看就动。

ARP协议的数据也并不是直接发送到局域网中,而是交付给MAC帧协议进行封装,然后再发送到局域网中:

图
ARP协议被交付给MAC帧协议后,给ARP协议封装了报头,如上图红色框中所示。

  • 注意到源MAC地址、目的MAC地址在以太网首部ARP请求中各出现一次。
  • 对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的。

👑ARP缓存表

ARP协议建立了主机IP地址和MAC地址的映射关系:

  • 在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,却不知道目的主机的MAC地址。
  • 数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃。

因此在网络通信前必须通过ARP协议获得目的主机的MAC地址。

图
如上图所示,主机MAC1在收到一个数据帧以后,它只能从IP协议中找到目标主机的IP地址,并不知道目标主机的MAC地址。

所以主机MAC1先构建一个ARP请求,其中硬件类型,协议类型,两个长度字段都是固定参数,op字段填1,表示这是一个ARP请求,发送端就是自己,所以发送端MAC地址为MAC1,发送端IP地址为IP1,目的MAC地址并不知道,使用0xFFFFFFFFFFFF,目的IP填IP7

然后交给MAC帧协议封装,MAC帧首部中MAC目的地址并不知道,所以使用0xFFFFFFFFFFFF填充,源MAC地址就是自己的MAC1,因为这是一个ARP请求,所以协议类型为0806,然后将这个数据帧发送出去。

  • 局域网中,主机号都是1的IP地址是一个广播地址,如192.168.1.255
  • 发送给广播IP地址的数据帧,局域网中的所有主机都要接收并且进行处理。
  • 正常的数据帧其他主机也能看到,但是在数据链路层就丢弃了,而广播地址的不会丢弃,会交付给上层做进一步处理。

主机MAC1广播了这个数据帧后,局域网中的所有主机都接收这个数据帧,首先在数据链路层发现这个数据帧中的MAC目的地址是0xFFFFFFFFFFFF,它无法处理,所以解包后根据帧类型0806交付给了上面的IP层。

IP层拿到ARP数据以后,首先看op字段(不考虑固定参数),发现该字段的值是1,说明这是一个ARP请求,然后再看目的IP地址和自己主机的IP地址是否相符。

如果不符则直接抛弃,不作响应,如果相符则构建响应。此时其他主机都将这个ARP请求抛弃了,只有主机MAC7发现目的IP地址和自己的IP地址相符,都是IP7,说明这是有人要获取它的MAC地址。

主机MAC7构建ARP响应:
图
此时主机MAC7知道这是给主机MAC1ARP响应,将对应字段填充好,此时是一个ARP响应,所以op字段是2,其他字段本喵不解释。然后交给MAC帧协议进行封装。

MAC帧协议中将头部中的目的MAC地址和MAC源地址,以及帧类型填充为0806后,发送给主机MAC1

  • 具体字段内容可以参照上图。

此时局域网中的所有主机仍然能看到这个数据帧,但是在数据链路层对比时发现目的MAC地址是MAC1,所以都将其抛弃了,不再向上分用给IP层。

主机MAC1收到这个数据帧后,通过对比自己的MAC地址和数据帧中的目的MAC地址,发现这是给自己的,所以进行解包,然后根据帧类型0806将有效载荷分用给ARP协议。

ARP协议首先op字段,发现这是一个ARP响应,说明这是自己曾经要获取MAC地址请求的响应,然后将发送端的MAC地址MAC7和发送端的IP地址IP7取出来,放入ARP缓存表中。

然后在将IP层的数据交给MAC帧协议进行封装,按照ARP缓存表中的映射关系填充报头,将MAC7填到目的MAC地址帧,再发送出去给主机MAC7

此时主机MAC1就能成功将数据准确的发送给主机MAC7,成功完成网络通信。

  • 每个主机在收到ARP数据以后,必须先看op字段。
  • 通过op字段可以区分这是别人向自己发起的ARP请求,还是自己曾经发起ARP请求的响应。

ARP协议虽然处于数据链路层,但是它的字段内容却涉及到数据链路层(MAC地址)和网络层(IP地址),所以说它工作在数据链路层和网络层之间。


图
通过指令arp -a可以查看当前机器上的ARP缓存表,如上图所示。可以看到,每一个IP地址都对应一个MAC地址,这些主机都位于一个局域网内,根据缓存表的对应关系就可以在IP层路由后准确的将数据发送到指定MAC地址处的主机上。

  • 每一个节点都会有这样的一个ARP缓存表。
  • 缓存表中的表项有过期时间(一般为20分钟),如果20分钟内没有再次使用某个表项,则该表项失效。
  • 下次还要发ARP请求来获得目的主机的硬件地址。

我们知道,在子网划分中的规则下,只有入网的设备才有IP地址,如果某一个主机断网很久了,另一台新主机使用这个IP地址,在其他主机给这个新主机发送数据的时候,ARP缓存表中的MAC地址仍然是旧主机的MAC地址,所以这台新主机收不到数据。

所以,ARP缓存表必须每隔一段时间就更新一次,如果是第一次给某台主机发送数据,则必须先进行ARP请求获取MAC地址。


图
在MAC协议帧类型中,还有一个8035RARP协议,这是一个反向的ARP协议。

有时候发送方主机可能会只知道对方的MAC地址,而不知道对方的IP地址,此时就发送一个RARP请求,获取目标MAC地址主机的IP地址。都已经知道源MAC地址和目的MAC地址了,所以这个过程非常简单,大家可以自行解决。

  • RARP协议使用的情况非常少,局域网中大部分跑的还是使用ARP协议。

🦺回顾整个协议栈

图
如上图所示,便是本喵讲解整个网络协议栈主脉络。

  • 主机A:

用户在应用层写好数据以后,通过HTTP或者HTTPS协议封装,将报文交付给传输层的TCP或者UDP协议。

如果是使用TCP协议,则报文被先放到了发送缓冲区中,操作系统在合适的时候将其封装并交付给网络层IP协议。如果使用的是TCP协议,则将报文封装并直接交付给网络层的IP协议。

网络层的IP协议在收到数据段后再将其封装,在IP报头中填充目的IP,源IP等字段,然后将数据报交给数据链路层的MAC帧协议。

  • 路由器:

MAC帧协议将数据帧通过局域网交给下一跳路由器,路由器的数据链路层收到数据帧后进行解包分用给上层的IP协议,IP层根据目的地址进行路由,然后再将新的数据报封装重新交给数据链路层。

MAC协议再将数据报交给下一跳路由器,如此往复,最终将数据帧交到了目标主机所在的局域网路由器处。

该路由器根据ARP缓存表中的映射关系,将数据发送给目标IP对应的MAC地址处的主机。

  • 主机B:

主机B的数据链路层收到数据后,通过对比发现MAC帧报头中的目的MAC地址和自己的MAC地址相符,所以进行解包,然后根据帧类型的0800将有效载荷分用给网络层的IP协议。

IP协议发现该数据报中的目的IP地址和自己的相符,所以进行解包,去掉IP报头,根据报头中的协议类型将有效载荷分用给传输层的UDP或者TCP协议。

传输层收到数据段后,将报头解包,并且根据报头中的目的端口号,将有效载荷交给应用层的HTTP或者HTTPS协议。

应用层收到报文后,进行解包,将报头和有效载荷分离,对发送过来的数据进行处理。


这就是依靠协议栈的整个网络通信过程,每一层中的详细细节本喵都有对应的文章在详细讲解,这里仅仅是一个宏观上的描述。相信到了这一步,我们对整个协议栈的认识和理解就更加透彻了。

🦺总结

对于数据链路层,重点理解数据帧在局域网中是如何传送的,局域网中的主机又是如何处理数据帧的,以及如何通过ARP协议获取目的主机的MAC地址,进而建立ARP缓存表的。

到次,本喵对于整个网络通信的过程便讲解完毕了,虽然讲解的协议不多,但是这些都是每一层中最重要的协议。网络是非常复杂的,充斥着多种多样的协议和规则,有兴趣的小伙伴可以继续深入了解。

相关文章:

【网络】数据链路层——MAC帧协议 | ARP协议

🐱作者:一只大喵咪1201 🐱专栏:《网络》 🔥格言:你只管努力,剩下的交给时间! 来到数据链路层后,完整的数据被叫做数据帧,习惯上称之为MAC帧。 MAC帧协议 | A…...

【Spring Boot】Spring Boot自动加载机制:简化应用程序的启动

在微服务盛行的今天,快速搭建和启动应用程序变得至关重要。Spring Boot作为Java生态系统中主流的框架,其自动加载机制使得开发者能够快速构建和启动应用程序。本文将详细介绍Spring Boot的自动加载机制,并通过代码示例加以说明。 首先&#…...

centos7搭建apache作为文件站后,其他人无法访问解决办法

在公司内网的一个虚拟机上搭建了httpsd服务,准备作为内部小伙伴们的文件站,但是搭建好之后发现别的小伙伴是无法访问我机器的。 于是寻找一下原因,排查步骤如下: 1.netstat -lnp 和 ps aux 先看下端口和 服务情况 发现均正常 2.…...

【开个空调】语音识别+红外发射

废话少说,直接上空调板子:YAPOF3。红外接收发射模块用的某宝上发现的YF-33(遗憾解码还没搞清楚,不然做个lirc.conf功能才多)。最后是语音识别用的幻尔的,某宝自然也有,它是个i2c的接口。 本篇胡说八道其实纯粹为了留个…...

【hibernate validator】(二)声明和验证Bean约束

首发博客地址 https://blog.zysicyj.top/ 一、声明bean约束 1. 字段级别约束 不支持静态类型字段 验证引擎直接访问实例变量,不会调用属性的访问器 在验证字节码增强的对象时,应适用属性级别约束,因为字节码增库无法通过反射确定字段访问 pac…...

Redis持久化机制之RDB,AOF与混合AOF

Redis是一款高性能的NoSQL数据库,它的速度非常快,同时也支持多种持久化机制,其中最常用的是RDB和AOF,还有一种混合AOF方式。那么这些持久化机制到底是什么,有什么不同呢? RDB是Redis默认的持久化方式&…...

为啥外卖小哥宁愿600一月租电动车,也不花2、3千买一辆送外卖!背后的原因......

大家好!我是菜哥! 又到周末了,我们聊点非技术的东西。最近知乎“为何那些穿梭于城市大街小巷的外卖小哥,宁愿每月掏出600块租一辆电动车,也不愿意掏出2、3千买一辆呢?” 冲上热榜! 听起来有点“…...

分布式定时任务框架Quartz总结和实践(2)—持久化到Mysql数据库

本文主要介绍分布式定时任务框架Quartz集成SpringBoot持久化数据到Mysql数据库的操作,上一篇文章使用Quartz创建定时任务都是保存在内存中,如果服务重启定时任务就会失效,所以Quartz官方也提供将定时任务等信息持久化到Mysql数据库的功能&…...

Linux 服务器搭建配置,开发效率一飞冲天 - Centos 篇

大家好,我是比特桃。最近白嫖了一台 Centos 云服务器,用来做日常开发,特此记录一下搭建配置的过程。 我之前有篇文章是基于 Ubuntu 的:Linux 服务器搭建配置,开发效率一飞冲天 - Ubuntu 篇 如同个人电脑一样&#xff0…...

Day46|leetcode 139.单词拆分

leetcode 139.单词拆分 题目链接:139. 单词拆分 - 力扣(LeetCode) 视频链接:动态规划之完全背包,你的背包如何装满?| LeetCode:139.单词拆分_哔哩哔哩_bilibili 题目概述 给你一个字符串 s 和一…...

深入理解高并发编程 - Thread 类的 stop () 和 interrupt ()

stop() stop() 方法被用于停止线程。然而,需要注意的是,stop() 方法已经被标记为已废弃(deprecated),并且不推荐使用。这是因为使用该方法可能导致不可预料的问题和数据不一致性,因此它被认为是不安全的。…...

C语言之三子棋游戏实现篇

目录 主函数test.c 菜单函数 选择实现 游戏函数 (函数调用) 打印棋盘数据 打印展示棋盘 玩家下棋 电脑下棋 判断输赢 循环 test.c总代码 头文件&函数声明game.h 头文件的包含 游戏符号声明 游戏函数声明 game.h总代码 游戏函数ga…...

jupyter notebook 插件nbextensions的安装

安装步骤: 1、打开 jupyter notebook,新建一个 python 文件; 2、 分别输入以下代码,然后运行,出现 warning 不影响使用,如果出现 errors,则说明下载有问题: !python -m pip install…...

Spring boot 集成单元测试

1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> 2. 3.编写测试类 package com.enterprise;import com.enterpr…...

基于C++的QT实现贪吃蛇小游戏

文章目录&#xff1a; 一&#xff1a;效果演示 二&#xff1a;实现思路 三&#xff1a;代码实现 widget.h widget.cpp main.cpp 一&#xff1a;效果演示 效果图◕‿◕✌✌✌ 代码下载 二&#xff1a;实现思路 通过按键控制蛇的移动&#xff0c;每吃一个商品蛇身就会加长…...

Spring Boot整合RabbitMQ之路由模式(Direct)

RabbitMQ中的路由模式&#xff08;Direct模式&#xff09;应该是在实际工作中运用的比较多的一种模式了&#xff0c;这个模式和发布与订阅模式的区别在于路由模式需要有一个routingKey&#xff0c;在配置上&#xff0c;交换机类型需要注入DirectExchange类型的交换机bean对象。…...

行式存储与列式存储

1.概述 数据处理大致可分为两大类&#xff0c;联机事务处理OLTP(on-line transaction processing) 和联机分析处理OLAP(on-line analytical processing)。 OLTP是传统关系型数据库的主要应用&#xff0c;用来执行一些基本的、日常的事务处理&#xff0c;比如数据库记录的增、删…...

windows上sqlserver的ldf日志文件和数据mdf文件分别放到不同的磁盘

之前我的windows上已安装好了sqlserver2017&#xff0c;有一个名为TestDb的数据库。ldf文件和mdf文件都一起放在D:\Database目录下。现在需要把ldf日志文件到E盘的database目录下。 重要的事情先说三遍 先停止网关&#xff08;例如nginx&#xff09;并备份数据库 先停止网关&am…...

vue3+uni——watch监听props中的数据(组件参数接收与传递defineProps、defineEmits)

案例说明 A页面引用的子组件B A页面 <template><view>//引用组件<serviceOrder change"change" :list"list" :current"type"></serviceOrder></view> </template><script setup>import serviceOrd…...

mybatis与spring集成与spring aop集成pagehelper插件

Mybatis与Spring的集成 Mybatis是一款轻量级的ORM框架&#xff0c;而Spring是一个全栈式的框架&#xff0c;二者的结合可以让我们更加高效地进行数据持久化操作。 Mybatis与Spring的集成主要有两种方式&#xff1a;使用Spring的Mybatis支持和使用Mybatis的Spring支持。 使用…...

Mybatis基础

...

TypeScript-- 配置Typescript环境(1)ts 转js,tsc --watch 实时编译

文章目录 安装Typescript判断是否有运行权限编写第一Typescript文件手动编译Ts文件转Js文件实时编译 安装Typescript npm install -g typescript 判断是否有运行权限 命令行运行 tsc -v 遇到了权限问题 用管理员打开window自带的powershell 运行如下指令即可&#xff1a; Set-…...

Dockerfile快速搭建自己专属的LAMP环境,生成镜像lamp:v1.1,并推送到私有仓库

环境&#xff1a; CentOS 7 Linux 3.10.0-1160.el7.x86_64 具体要求如下&#xff1a; &#xff08;1&#xff09;基于centos:6基础镜像&#xff1b; &#xff08;2&#xff09;指定作者信息&#xff1b; &#xff08;3&#xff09;安装httpd、mysql、mysql-server、php、ph…...

Lottery抽奖项目学习第二章第一节:环境、配置、规范

Lottery抽奖项目学习第二章第一节&#xff1a;环境、配置、规范 环境、配置、规范 下面以DDD架构和设计模式落地实战的方式&#xff0c;进行讲解和实现分布式抽奖系统的代码开发&#xff0c;那么这里会涉及到很多DDD的设计思路和设计模式应用&#xff0c;以及互联网大厂开发中…...

OpenCV之reshape函数

函数原型&#xff1a; /** brief Changes the shape and/or the number of channels of a 2D matrix without copying the data.The method makes a new matrix header for \*this elements. The new matrix may have a different sizeand/or different number of channels. A…...

【JavaEE】Spring事务-@Transactional参数介绍-事务的隔离级别以及传播机制

【JavaEE】Spring事务&#xff08;2&#xff09; 文章目录 【JavaEE】Spring事务&#xff08;2&#xff09;1. Transactional 参数介绍1.1 value 和 transactionManager1.2 timeout1.3 readOnly1.4 后面四个1.5 isolation 与 propagation 2. Spring 事务隔离级别 - isolation2.…...

微信小程序canvas type=2d生成海报保存到相册、文字换行溢出显示...、文字删除线、分享面板

一、简介 做个简单的生成二维码海报分享&#xff0c;我做的时候也找简单的方法看能不能实现页面直接截图那种生成图片&#xff0c;原生小程序不支持&#xff0c;不多介绍下面有全部代码有注释、参数自行替换运行看看&#xff0c;还有需要优化的地方&#xff0c;有问题可以咨询…...

C++卷积神经网络

C卷积神经网络 #include"TP_NNW.h" #include<iostream> #pragma warning(disable:4996) using namespace std; using namespace mnist;float* SGD(Weight* W1, Weight& W5, Weight& Wo, float** X) {Vector2 ve(28, 28);float* temp new float[10];V…...

go 读取yaml映射到struct

安装 go get gopkg.in/yaml.v3创建yaml Mysql:Host: 192.168.214.134Port: 3306UserName: wwPassword: wwDatabase: go_dbCharset: utf8mb4ParseTime: trueLoc: LocalListValue:- haha- test- vv JWTSecret: nidaye定义结构体 type Mysql struct {Host string yaml:&…...

Redis 10 大数据类型

1. which 10 1. redis字符串 2. redis 列表 3. redis哈希表 4. redis集合 5. redis有序集合 6. redis地理空间 7. redis基数统计 8. redis位图 9. redis位域 10. redis流 2. 获取redis常见操作指令 官网英文&#xff1a;https://redis.io/commands 官网中文&#xff1a;https:/…...

科讯cms网站管理系统kesioncms/云服务器

LeetCode每日一题&#xff08;2020/3/5&#xff09; LeetCode这个月推出了每日一题打卡刷题计划&#xff0c;正好每天利用空闲时间打个卡&#xff0c;也在此记录总结一下。 这些题目都没有用数学方法求解&#xff0c;数学方法可以看LeetCode上的题解&#xff0c;讲的都非常详细…...

山东莱芜金点子信息港/伊春seo

sleep与wait区别&#xff1a;1、sleep方法是线程静态方法&#xff0c;wait方法是Object对象方法&#xff1b;2、sleep使线程休眠&#xff0c;不会释放锁&#xff1b;wait方法是在获取锁情况下进行等待的&#xff0c;等待时会释放锁&#xff1b;3、都可以响应中断。public class…...

wordpress注册没有密码/760关键词排名查询

项目接口文档管理之swagger-ui 首先引入swagger-ui的包文件其次是wagger的配置类第三是自定义接口说明第四是启动测试swagger2的常用注解说明@Api@ApiOperation@ApiImplicitParams@ApiModel@ApiResponses@ApiParam首先引入swagger-ui的包文件 <dependency><groupId...

建设银行辽宁分行招聘网站/哪里可以学seo课程

比如取1.80版本 git clone -b 1.18.0 https://github.com/passedbylove/poiji.git 转载于:https://www.cnblogs.com/passedbylove/p/11208336.html...

域名为www.com的网站/网站制作的费用

正则表达式模式修正符:i 忽略大小写m 多行视作一行g 全局匹配s .圆点匹配换行符,默认不包括换行x 空白字符除了被转义的或在字符类中的以外完全被忽略&#xff0c;在未转义的字符类之外的 # 以及下一个换行符之间的所有字符&#xff0c;包括两头&#xff0c;也都被忽略。e preg…...

动易 网站首页/百度站长工具平台

mysql有多种存储引擎&#xff0c;有些版本&#xff08;mysql5.5.5以前默认是MyISAM&#xff0c;mysql5.5.5以后默认是InnoDB&#xff09;安装时默认的存储引擎是MyISAM&#xff0c;而MyISAM存储引擎是不支持事务处理的&#xff0c;所以才导致了项目中service层的某个方法事务失…...