tcp协议介绍,协议段格式(端口号,首部长度,窗口大小,序号,确认序号,6个标志位),流量控制,确认应答机制,捎带应答,三次握手的双方认知不一致问题

目录

tcp协议

介绍

传输控制协议

图解

全双工

缓冲区

控制

tcp协议段格式

数据在不同层的名称

图解

​编辑

端口号

首部长度 

窗口大小 -- 引入

前提

流量控制

确认应答机制

窗口大小 -- 介绍

序号 -- 引入

确认应答机制的进一步探讨

如果应答丢失

捎带应答

发送多条数据 

序号 -- 介绍

确认序号

引入

介绍 

示例

为什么要有两个序号

标志位

引入

介绍

SYN

FIN

PSH

引入

写阻塞问题

解决

ACK

RST

引入

应用场景1 

引入 -- 连接结构体

双方认知不一致

应用场景2

三次握手

双方不一致 

应用场景3

总结

URG(紧急指针字段)

引入

介绍

如何读写

应用


tcp协议

介绍

传输层协议介绍(tcp,udp),可靠性和不可靠性_可靠传输服务和不可靠传输服务 udp tcp-CSDN博客

网络通信中字节流存在的问题,tcp协议特点,自定义协议(引入+介绍,序列化反序列化介绍,实现思路)_自定义tcp通信协议-CSDN博客

tcp协议的应用场景比udp要更广

  • 大多数的应用层协议底层都使用的是tcp,比如http协议

传输控制协议

图解

所以,我们把数据通过接口发送,其实就相当于把数据交给了内核(传输层在内核里)

  • 就像我们使用文件接口将数据写入文件一样,都是交到了内核中的缓冲区

一个是tcp协议专用的发送缓冲区,一个是文件专用的io缓冲区

  • 只不过经过的硬件设备不同,一个是网卡,一个是磁盘
  • 所以,都属于io过程  

全双工

从tcp协议角度来看

  • 发送的过程就是将自己发送缓冲区里的内容交到(拷贝到)对方的接收缓冲区里

当一方读取时

  • 如果此时自己的接收缓冲区里没有数据(也就是资源不就绪),就会阻塞,直到有数据进来再唤醒

因为一个文件描述符配套了两个缓冲区

  • 所以tcp协议也是可以既读又写的,也就是全双工

缓冲区

缓冲区其实就是由多个4kb大小的内存块组成的,并且每个内存块都有对应的struct page结构来管理

然后以某种数据结构将结构体组织起来

那么对内存的管理,就变成了对这一堆结构体做管理

虽然这些内存块都是4kb,但用处有不同

有的用来作为文件缓冲区,有的作为网络缓冲区

控制

而tcp协议之所以可以实现控制,就是因为它有发送缓冲区

  • 它可以在对方接收缓冲区满时,先将数据存放着,等有位置了再发

而udp连发送缓冲区都没有,也就没有控制能力,除非有应用层帮它手动搞一个

tcp协议段格式

数据在不同层的名称

我们之前说过,数据在每一层都有自己的名字

  • 应用层 -- 请求/响应
  • 传输层 -- 数据段
  • 网络层 -- 数据报
  • 链路层 -- 数据帧

图解

大致分为三层:

  • 标准报头(固定20字节)
  • 选项(这里我们不介绍)
  • 有效载荷

其中,标准报头+选项=报头

端口号

通过报头里的目的/源端口号,我们就可以定位上层服务 

首部长度 

我们该分离报头和有效载荷呢?

  • 虽然标准报头的长度固定是20字节,但选项并不固定(可以有,可以没有)

而标准报头中的首部长度记录的就是整个报头的长度

  • 首部长度-20=选项长度

因为是4位,所以最大长度为2^4-1=15字节?

  • 也就是[0000,1111]
  • 但是光标准报头就有20字节了耶,肯定是放不下的

那它究竟是什么?

  • 其实它是以4字节为单位

打个比方

  • 就像有些人说自己的工资是1500,有人说自己是1.5,其实就是单位不同

所以

  • 报头最长是15*4=60字节,选项最长是40字节
  • 这种固定长度+自描述字段,就可以知道其他部分的长度了

知道了每个部分的长度,咱们就来具体说说,如何分离报头和有效载荷

  • 先读取20字节,拿到标准报头
  • 再取出首部长度字段,换成10进制后*4->报头长度,-20=选项长度
  • 再读取出选项,剩下的就是数据了

窗口大小 -- 引入

那报头里的窗口大小又是什么呢?

在介绍窗口大小之前,首先我们要明确一个前提

前提

一旦被发送了出去,在到达对方的传输层前,都是具有完整报头的数据

以及要介绍一下tcp的流量控制 :

流量控制

在这个场景下:

  • 当应用层忙碌时,可能来不及进行读取,但另一方并不知道,还在持续发送
  • 一旦那方的接收缓冲区满了,还继续发送,就会出现丢包
  • 这样显然不可靠

而tcp协议的控制能力就体现在:

  • 它可以在一方缓冲区满时,控制另一方的发送速度减慢/暂停发送
  • 这种控制发送数据的速度的能力,从而规避大面积丢包的能力,就叫做流量控制

但我们之前也说过:

  • tcp的可靠性还体现在它可以丢包重传
  • 那是不是就没必要进行流量控制了呢?
  • 确实是这样,但用了比不用好

想一想

  • 一个数据历经多个设备来到目标主机,结果本身没出错,就因为对方缓冲区满了就要重传
  • 这期间得浪费多少资源?效率自然就下降了
  • 所以,流量控制是必要的 

但是,仔细想想,tcp协议是如何让双方知道对方缓冲区情况的呢?

tcp保证可靠性的策略有很多,但其中最基本的是 -- 确认应答机制

确认应答机制

当客户端向服务器发送数据:

  • 服务器都要给客户端返回响应,来确定自己已经收到了数据
  • 反过来也是一样,这样就能知道对方收到了没
  • 就像两个人打电话,一方会询问对方能不能听见,直到对方有回应才能确定对方听见了

所以,我们重新来梳理tcp协议的通信过程:

  • 当客户端向服务器发送数据,服务器收到后会立即返回应答
  • 如果客户端当前发送速度过快,对方来不及接收,就会调整自己的发送速度

如何调整呢?

  • 自然是由服务器的接收能力(也就是服务器的接收缓冲区的剩余空间大小)决定
  • 其实就很像生产消费者模型里,生产者和消费者的行为由对方资源数量决定

但是,cp模型里是由条件变量通知各个进程的,这里的客户端如何知道服务器的情况呢?

  • 结合上面说的,服务器会给客户端返回应答+基于tcp协议通信时,一定带有完整报头+这里准备要介绍的窗口大小
  • 可以猜出,这个窗口大小的字段就是用来记录服务器剩余空间大小
  • 这样就可以动态调整自己的发送速度了

反过来也是一样的:

  • 因为服务器也需要给客户端发送响应,也可能会出现客户端的接收缓冲区满的情况,也需要流量控制

窗口大小 -- 介绍

那么,总结一下

  • 这个窗口大小,填写的就是自己接收缓冲区的剩余空间大小,用于流量控制

序号 -- 引入

确认应答机制的进一步探讨

假设a给b发送数据

  • 当b收到数据后,会返回a一个应答,来让a知道自己已经收到了
  • 当a收到这个应答,就知道自己发的数据b已经收到了
  • 然后a又给b发了应答,以此来表示自己收到了b的应答...

这样无穷无尽的...

但是可以看出:

  • 只要一方收到了应答,就能知道对方收到了数据.也就能保证该条数据的可靠性

如果我们从某处截断这个过程

  • 那么,此时最新的消息是无应答的,也就不能保证接收方收到了(至少发送方是无法知道的)
  • 所以,无法保证发出的数据是百分百可靠的

但最新消息之前的消息都是 -- 数据,应答,应答的应答....

  • 这些都是可以保证双方的可靠性的

所以:

  • 其实,没有必要对[应答]再应答,我们只需要保证局部上的可靠性
  • 因为我们无法保证每条消息都是可靠的,那么索性就简单一点,让那个不可靠的是第一个应答即可

比如:

  • 只要客户端向服务器发数据后,收到了服务器的应答即可
  • 这就已经能让客户端达成了通信的目的 -- 让服务器收到了数据

不需要再让服务器知道客户端收到了应答,跟它没关系了

  • 我们只保证单方向的可靠性就行
  • 反过来也是一样,服务器只要保证客户端收到数据了即可,不需要让客户端知道服务器收到了应答

如果应答丢失

但是,万一这个应答中途不小心丢了呢?

  • 发送方不知道
  • 而接收方以为对方没有发送应答,就代表对方没有收到我发送的消息

仔细想想,接收方如何知道对方有没有返回应答?

  • 等待对方的消息

那就会有两种情况,等到了/没等到

  • 但接收方难道会一直等吗?
  • 要是就是应答丢包了/甚至自己的消息在中途丢失了怎么办,总不能因为这一条消息把接收方卡死在这了吧
  • 所以,它只会等待一段时间,时间过后还没有收到,接收方就认为数据已丢失(无论是自己的或者对方的),就会进行重传
  • 反之,对方也采取同样的策略对待发送的数据

上面的过程其实就像我们现实中打电话

  • 当你询问对方是否能听见,如果对方有回应,你就知道对方听见了
  • 如果没有,你就不确定对方到底听没听见,你会重复询问,直到有回应
  • 而重复了几次依然没有,我就会挂电话了,另找个时间再打(对应tcp协议的重传,不一定一模一样哈,只是个例子)

捎带应答

按照我们上面说的,一方收到数据后会先给对方发送应答,再进行通信

  • 这就可能会导致效率问题

就像:

你吃饭了没       

                         收到

                         没吃呢

收到

我也没吃呢,要不咱一块去吃

                          收到

                          那走

收到

  • 是不是这种通信方式明显是没有必要的?
  • 明明可以合并在一起说,非要把应答和响应拆开发两次
  • 把应答和响应结合起来,这种策略叫做捎带应答

发送多条数据 

如果发送方连续给接收方发送多条消息怎么办?

  • 注意,双方一定是并发(你发你的,我收我的)的,串行(直到收到对方的应答再发下一条数据)效率可太低了

首先,我们先明确一点,发送的顺序不一定就是到达的顺序

  • 可能因为某种原因导致先发送的慢到达

而造成乱序,本身就是不可靠的一种体现

  • 也许本身就需要这些数据保持原顺序呢?
  • 也许打乱顺序会造成某些影响呢?

而tcp协议是具有可靠性的

  • 所以,它需要对这些数据进行排序

 

序号 -- 介绍

tcp缓冲区其实就是char数组

这里我们把char就看作是一个字节,然后数据被填充进去都是以字节排列的,所以天然就存在序号(也就是数组下标)

  • 而我们把每个报文的最后一个字节对应的下标,称为该条报文的序号
  • 这个图也只是示意图,并不是实际情况

所以,根据序号,我们就可以对收到的数据进行排序

确认序号

引入

按照我们上面的过程,发送方和接收方是一来一回的

  • 那么接收方收到多条消息时,同样也会发送多个应答

这里的应答并不一定会按照发送顺序返回

  • 先发送的可能因为某个原因后到达,总之顺序是不一定的
  • 但是!!!收到应答的发送方该如何知道对方是对哪条数据做的应答呢???

因为数据有可能会丢失

  • 所以一来一回的数量不一定相等,那就存在数据没有发送+接收成功

发送方该如何定位呢?

  • 也就是报头里的确认序号的作用

介绍 

确认序号是对应报文序号+1

为什么呢?

  • 它表示[确认序号]之前的字节我都已经收到了
  • 下次你要发送的数据从[确认序号]开始

比如

  • 一个报文里的序号是1000,当接收方收到后,返回的应答里的确认序号就是1001

这个设计有一个好处:

  • 当应答丢失了,它可以根据最大的确认序号来知道自己该重发哪些内容

示例

比如: 发送的报文序号有1000,2000,3000

收到的应答的确认序号只有3001:

  • 这说明1001,2001的应答都丢失了
  • 但根据确认序号的特性,能发送3001的确认序号,就一定是前3000个字节已经处理了
  • 所以不需要重传前2000个字节的数据,即使应答丢失
  • 也就是说,它可以允许少部分的应答缺失

如果收到的是两个1001:

  • 则说明序列号为2000的报文丢失
  • 第一个1001:收到1000后发送的应答
  • 第二个1001:收到3000后,但由于2000丢失,所以仍然发送1001,说明它仍然在期待1001字节开始的数据
  • 所以系统将重传2000的数据

为什么要有两个序号

为什么一定要把这两个序号分开呢?不能只定义一个变量来接收吗

  • 比如,发送方把它填充成序号,接受方填充成确认序号

但因为可能存在捎带应答,也就是--

  • 既是对发送方的应答(填充确认序号)
  • 又有接收方想要对发送方发送的数据(填充序号,因为这个数据也可能是连续发送,需要排序)

而又因为全双工

  • 双方地位是对等的,随时可能互发消息
  • 所以捎带应答的情况很普遍

所以,最好是把这两个序号分开

标志位

引入

 tcp建立连接/正常通信/断开连接,客户端都需要和服务器交互,并且服务器的行为均不同

  • 三次握手
  • 分离数据做出处理
  • 四次挥手

交互,也就是要发送tcp报文

  • 一定包含报头,数据可以没有

但是,一个报文如何对应多种行为呢?

  • 那么,tcp报文本身就得有不同的类型
  • 结合上面,我们不难猜出,报头中一定有字段可以表示报文类型 -- 6个标志位

介绍

tcp协议和报头是由os决定的,标志位也不例外

  • 这些标志位不能直接被用户改写,而是要通过os提供的系统调用来帮助修改 / 由系统自主决定 

SYN

用于标识该报文是否用来建立连接

  • 而我们建立连接使用的是connect函数
  • 联系起来则可以知道,connect函数会构建一个设置了SYN(置1)的报文发给服务器

 

FIN

用来告诉对方,自己想要断开连接

  • 比如,我们调用close来关闭套接字(用fd操作)

PSH

也就是push的缩写,从名字就可以知道,它用来催促对方交付数据

  • 具体应用于什么场景呢?
引入

tcp协议有两个缓冲区,有人往里放,有人往外拿

  • 如果用户不读取,接收缓冲区内就会堆积数据
  • 一直不读取,接收缓冲区满了后,发送缓冲区就会堆积,从而导致写阻塞

是不是很像cp模型

  • 生产者是系统 (将a主机发送缓冲区内的数据,发送到b主机的接收缓冲区内)
  • 消费者是用户 (将数据从接收缓冲区拿到用户层)

只不过这里是系统级别的cp模型

前面说的流量控制,换个视角看就是:

  • 在根据空间资源控制生产者的生产行为
  • 也就是发送过程的同步控制
写阻塞问题

接着上面说的写阻塞继续

  • 写阻塞后,写入方就得等待缓冲区腾出空间后再写入

等多久呢?腾出空间后又该如何得知呢?

有两种方式:

  • 发送方会定期询问对方是否有剩余空间 (记得吗,tcp的确认应答机制 -- 收到报文后会返回应答,在应答中可以带上空间大小)
  • 接收方如果剩余空间大小更新了也会通知发送方

这两种机制同时存在,哪个奏效了就算哪个

解决

如果多次询问无果,且没有收到空间更新的消息,自己的发送缓冲区又压力很大

  • 发送方就会发送带有PSH标志位(置1)的报文给对方,让对方赶紧把数据交付给上层来腾出空间
  • 这样可以宏观提高通信效率

说是压力很大,但这个机制会在还有一定空间时就触发,而不是满了再说

  • 所以对方还是可以接收到的

但如果对方就是不读取呢?

  • 毕竟读到应用层是需要客户端主动调用函数的

首先,我们先排除故意不读的情况

  • 一旦是这样,这个代码就是错的,我们不讨论它

所以,只能是当前客户端太忙才没有读取,但这里就不多介绍了

ACK

标识我们的报文是否具有应答属性

我们大部分的报文都默认将该位置1

  • 因为报文要么是单纯的应答/数据,要么是携带了数据的应答,是应答的可能性很高

而具体的类型就由是否有数据+ack是几来确认

  • 如果ACK为0,则是单纯的数据
  • 如果ACK为1,再看它是否携带数据
  • 是,则为携带了数据的应答报文
  • 否则为应答报文

RST

引入

建立连接一定会成功吗?

  • 当然不是
  • 通信过程中总会有各种问题出现

虽然tcp可靠,但也不是100%的可靠

  • 如果是客户端的异常操作把连接弄挂了/出现其他不可抗力的异常,再可靠也没办法,我们必须依赖应用层的逻辑来处理
  • 应用层可以实现逻辑来捕获这些错误并重试连接
应用场景1 
引入 -- 连接结构体

服务端可以存在多个建立好的连接

  • 毕竟服务肯定是面向大众的,一定会有多个客户端连接
  • 也就会维护多份多份通信数据

要不要管理?

  • 当然要,所以系统内会为了维护连接而创建结构体
  • 该结构体内可能包括 : 连接的属性,起始序号,确认序号,建立连接的时间,双方的端口号,缓冲区的位置等等

所以,创建/维护连接都是有成本的

  • 三次握手成功后,需要创建内核数据结构,并初始化,一直保存结构到断开连接
双方认知不一致

这样的话

  • 有可能三次握手虽然成功了,但内核结构没有建立好/建立过程中出现了问题

那么就可能其中一方的内核数据结构没有正确初始化或建立

  • 那么客户端,服务端对建立连接的结构认知是不一样的,这种情况下是无法正常通信的
  • 所以就需要服务器给客户端发送一个设置好RST标志位的报文,强制断开连接,重新来过
应用场景2
三次握手

这是三次握手的情况

注意哈,虽然这里只写了标志位

  • 但其实是设置好该标志位的tcp报文

至于为什么斜线呢?

  • 我们把纵轴看作是时间轴,而发送和接收肯定是具有时间差
  • 所以是斜线
双方不一致 

对于客户端来说

  • 发送完应答就完成了三次握手(没办法,因为不能再为应答发应答了,不然就无限循环了)
  • 然后就会建立连接结构体,准备之后的通信

对于服务端来说

  • 收到了应答才算完成

基于这样的情况,就很可能出现双方认知不一致的结果:

  • 在三次握手中,前两条报文都是有应答的,而第三条没有,客户端只能赌这条报文被服务端收到了
  • 那万一就是丢失了呢?
  • 那么服务端没有收到应答,就不认为连接建立好了
  • 可客户端以为连接建立好了,它会从connect函数返回,进入通信流程

也就是发送数据给服务器

  • 那服务器收到数据就懵啦,怎么还没建立好连接就开始通信了,咱们不是遵守的同一套协议吗
  • 所以,服务端只能认为和客户端有误会,客户端以为已经建立好了,实际并没有
  • 于是服务器发送带有RST标志位的报文给客户端,告诉对方:别通信啦,你连接都没建立好呢,赶紧重新建立一下
  • 这样客户端收到后,就会意识到,原来我刚刚建立的连接是有问题的
  • 于是就会重新开始三次握手流程
应用场景3

服务器内部出现异常,重启/其他什么的,把数据清空了

  • 但客户端并不知情啊,依然对服务器发送数据
  • 这时候肯定是无法通信的,客户端以为连接还在,实际上另一端早就没有了
  • 也需要重新建立连接  

总结

这个标识位用于 -- 在双方建立连接异常的情况下,对连接状态进行重置

  • 在建立连接中/通信中,都有可能存在异常

就是我们经常在网页上看到的,"连接已重置"

URG(紧急指针字段)

引入

tcp协议的可靠性,保证了数据可以按序处理

但是,如果我们就是想让某个数据被优先处理该怎么办?

  • 就只能引入新的机制了
介绍
  • 当URG为0时,表示无效,紧急指针无意义
  • 为1时,紧急指针有效

说了半天,紧急指针是个啥呢?

  • 它也是tcp标准报头中的一个字段
  • 存放的是紧急数据在该报文的数据部分的偏移量

但是,只有偏移量,我们怎么知道紧急数据有多少呢?

  • 紧急数据默认是一个字节,并且无法修改这个上限
  • 因为tcp要保证主体数据是有序的,可以插队,但不能太多
如何读写

send /recv函数中有一个参数flags

  • 它可以被填充成 MSG_OOB
  • 它用来表示,发送的数据是带外数据(也就是紧急数据)
应用

当一个服务本身没有问题,没有挂掉,只是响应很慢/没有响应时

  • 也许是在执行周期性任务,比较吃资源
  • 也许当前计算量太大

我们需要知道服务器此时处于什么情况,就会向服务器询问

  • 不然只是单纯等待吗,那得等到啥时候,有问题就得解决问题,首先得知道到底是在干啥

所以,服务器需要支持这种不同于普通通信的询问机制 -- 可以读取紧急数据+定义多个服务器状态字段

  • 并且,如果让询问也乖乖地和普通报文一样排序,就是本末倒置了
  • 本来我们就是因为没有响应才去询问的,等轮到处理询问的时候肯定已经有响应返回了,还询问什么
  • 所以,需要让他插队,也就是发送紧急数据(可以被优先处理)

然后服务器会专门有例程来读取紧急数据

  • 又因为紧急数据很小,很快就可以处理完成
  • 所以,可以立即返回当前服务器的状态编号

这样客户端就可以知道此时服务器处于什么状态了

虽然有如上的应用场景,但我们一般用不到

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

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

相关文章

基于Android studio 使用SQLite数据库完成登录注册功能——保姆级教程

🍅文章末尾有获取完整项目源码方式🍅 点击快捷传送地址: 保姆级教学——制作登陆注册功能页面 目录 一、准备工作 二、创建相关文件 三、页面布局 四、DabaHelper帮助类的编写 五、RegisterActivity注册页面 六、LoginActivity登录页面…

clion读取文件设置为读取当前目录下的文件

1.问题 使用vs读取文件时一切正常 但是同样的代码在clion中无法正常执行 原因 原因:clion的源文件找不到input.txt文件的位置 需要设置工作目录,例如此时input.txt在当前目录下,那么就设置 设置当前文件的工作目录为$FileDir$即可&am…

通过 NIO + 多线程 提升硬件设备与系统的数据传输性能

一、项目展示 下图(模拟的数据可视化大屏)中数据是动态显示的 二、项目简介 描述:使用Client模拟了硬件设备,比如可燃气体浓度检测器。Client通过Socket与Server建立连接,Server保存数据到txt文件,并使用W…

操作系统总结4----死锁的处理策略总结

目录 2.4.2 死锁的处理策略-----预防死锁 (1)知识总览 (2)破环互斥条件 (3)破环不剥夺条件 (4)破环求情和保持条件 (5)破环循环等待条件 总结 2.4.3 死…

广告圈策划大师课:活动策划到品牌企划的深度解析

对于刚接触营销策划的新人来说,在这个知识密集型行业里生存,要学习非常多各种意思相近的概念,常常让人感到头疼,难以区分。 这里对这些策划概念进行深入解析,帮助您轻松理清各自的含义和区别。 1. 活动策划&#xff…

操作抖音小店一直不出单怎么办?只需要做好这两点就可以了!

大家好,我是电商小V 最近很多新手小伙伴来咨询我说自己操作抖音小店,自己的店铺长时间不出单应该怎么办?今天咱们就来详细的说一下, 咱们要清楚的就是自己的店铺不出,只需要咱们做好这两点就可以了, 第一点…

华为机考入门python3--(29)牛客29-字符串加解密

分类:字符变换 知识点: 字符是字母 char.isalpha() 字符是小写字母 char.islower() 字符是数字 char.isdigit() b变C chr((ord(b) - ord(a) 1) % 26 ord(A)) 题目来自【牛客】 # 加密 def encrypt_string(s):result ""for ch…

C++的AVL树

目录 基本概念 插入的语言分析 LL右旋 RR左旋 额外结论及问题1 LR左右旋 RL右左旋 额外结论及问题2 插入结点 更新bf与判断旋转方式 旋转代码实现 准备工作一 LL右旋的实现 RR左旋的实现 准备工作二 LR左右旋的实现 RL右左旋的实现 完整代码 基本概念 1、…

抖音小店新规重磅来袭!事关店铺流量!商家的福音来了?

大家好,我是喷火龙。 就在前两天,抖店发布了新规,我给大家总结了一下,无非就是两点。 第一点:保证金下调,一证开多店。 第二点:新品上架破10单,有流量扶持。 咱来细细的解读&…

无人机助力光伏项目测绘建模

随着全球对可再生能源需求的不断增长,光伏项目作为其中的重要一环,其建设规模和速度都在不断提高。在这一背景下,如何高效、准确地完成光伏项目的测绘与建模工作,成为了行业发展的重要课题。近年来,无人机技术的快速发…

【产品经理】如何培养对市场的洞察力

引言:        在最近频繁的产品管理职位面试中,我深刻体会到了作为产品经理需要的不仅仅是对市场和技术的敏锐洞察,更多的是在复杂多变的环境中,如何运用沟通、领导力和决策能力来引导产品从概念走向市场。这一系列博客将分享…

技术驱动未来,全面揭秘 Sui 的生态发展和布局

在不到一年的时间里,由 Mysten Labs 团队创立的 Layer1 区块链 Sui 迅速崛起,成功跃升至去中心化金融(DeFi)的前十名。根据 DeFi Llama 的数据,Sui的总锁定价值(TVL)在短短四个月内增长超过 100…

堆的实现

前言:本文讲述堆实现的几个难点,注意本文主要是以实现为主,建议有些基本概念认识的人阅读。 目录 1.堆 2.堆的实现 堆结构的定义: 要实现的接口: 接口的实现: 堆的初始化和销毁: 向堆中插…

【简单介绍下链表基础知识】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

第八届能源、环境与材料科学国际学术会议(EEMS 2024)

文章目录 一、重要信息二、大会简介三、委员会四、征稿主题五、论文出版六、会议议程七、出版信息八、征稿编辑 一、重要信息 会议官网:http://ic-eems.com主办方:常州大学大会时间:2024年06月7-9日大会地点:新加坡 Holiday Inn …

OA界面这么香吗?总有老铁私信,让我多发点,他好参考。

OA的确是B端系统应用最为广泛的一种,这次再给大家分享十来个页面,希望对他们的界面提升有所帮助。 举报 评论 3

计算机考研|408开始的晚,怎么入手复习?六个月保姆级规划

万事开头难,特别是408 大家在第一遍复习408的时候,基本上都有这个问题,就是复习速度慢,理解成本高,因为数据结构,计算机组成原理这些都是大一大二开始学的内容,等到自己准备考研的时候&#xf…

洗地机哪个牌子最好用?2024洗地机排行榜

随着人们生活水平的提升,智能清洁家电已经成为日常生活中的必需品。如今的清洁家电市场上,洗地机、吸尘器和扫地机器人等设备各有其独特的功能和优势。洗地机结合了扫、拖、吸和自清洁等多种功能,不仅可以处理干湿垃圾,还能高效清…

打破传统相亲模式,这几款靠谱的相亲软件助你脱单

相亲软件在当今社会已经变得越来越普遍,市面上有众多相亲软件可供选择,但哪些相亲软件好用呢?下面介绍几款备受好评的相亲软件,帮助你在茫茫人海中找到那个对的人! 1、一伴婚恋 这个APP它最大的优点就是信息真实靠谱…

mac上简单实现一个java调用C接口的JNI

目录 安装JDK及配置环境变量写Java代码生成头文件实现本地方法编译本地代码运行 Java 程序总结步骤 安装JDK及配置环境变量 参考:MAC系统安装JDK1.8及环境变量配置 写Java代码 // 文件名:Calculator.java public class Calculator {// 声明本地方法pu…