UDP_TCP

目录

  • 1. 回顾端口号
  • 2. UDP协议
    • 2.1 理解报头
    • 2.2 UDP的特点
    • 2.3 UDP的缓冲区及注意事项
  • 3. TCP协议
    • 3.1 报头
    • 3.2 流量控制
    • 2.3 数据发送模式
    • 3.4 捎带应答
    • 3.5 URG && 紧急指针
    • 3.6 PSH
    • 3.7 RES

1. 回顾端口号

  • 在 TCP/IP 协议中,用 “源IP”, “源端口号”, “目的IP”,“目的端口号”,“协议号” 这样一个五元组来标识一个通信(可以通过 netstat -n 查看)。

  • 端口号范围划分:

    • 0 - 1023:知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的。

      ssh(22),ftp(21),telnet(23),http(80),https(443)

    • 1024 - 65535:操作系统动态分配的端口号。客户端程序的端口号,就是由操作系统从这个范围分配的。

  • cat /etc/services:看到知名端口号。

  • 两个问题(详细见 网络基础(二)):

    • 一个进程是否可以bind多个端口号?  ------ 可以。
    • 一个端口号是否可以被多个进程bind?   ------ 不可以。

2. UDP协议

在这里插入图片描述

  • 以UDP为例:当我们在客户端的应用层,通过 sendto 系统调用,将数据发送到服务端,站在网络协议栈的角度看待,该数据实际上是先被拷贝到传输层(传输层属于OS),而这部分数据就是 UDP 中看到的数据,应用层的报文经由传输层时,OS会封装一层传输层的报头,即 UDP 报头。

    分装报头时,发送端会随机形成一个源端口,并填充目的端口号。其中的 UDP 长度代表的是整个 UDP 报文的长度,检验和则是检验整个报文在传输过程中是否出错。

    因此,我们过去在 udp_socket 编程时,客户端需要在发送请求的同时,填充服务端的端口号,以及定义端口号时,我们采用的类型是 uint16_t,这一切都是源于 UDP 的报头决定的!

  • 而因为网络通信时,报文在协议栈中自顶向下是要分装的,最后再自底向上解包分用。因此,我们需要解决

    • 报头和有效载荷的分离问题:固定报头长度。
    • 有效载荷是如何向上交付的问题:绑定目的端口号。
    • UDP 是面向数据报的,如何保证接收到的报文是完整的? ------ 通过报头长度确定,如果报头长度小于8字节,报头都有问题,整个报文直接丢弃;大于8字节,UDP长度 - 报头长度 = 数据长度。

2.1 理解报头

  • 我们在各种教科书上看到的报头都形如上图,但是报头究竟是个什么东西呢?

    一个描述报头的结构体,所谓报头,就是一个结构化的数据。

    struct udphdr {uint16_t src_port, dst_port;uint16_t udp_len, checksum;
    }
    

    但是,一个服务器是同时对接多个客户端的,因此服务器内是会存在大量的报文的,因此操作系统内可能积攒大量的报文,可能还没有向应用层进行交付,那么操作系统就需要对这些 UDP/TCP 报文管理起来。

    内核中存在一个 sk_buff 结构体,其中有 *data、*tail 两个字段的指针(指向同一位置),并且在内核中定义一段缓冲区,用户保存接收到的报文数据。假设应用层通过 sendto 将 “hello” 发送到传输层,那么在拷贝到传输层时,*data 指针就向前移动 5 个字节,用于存储上层发送的数据。接着,还需要定义一个 udphdr 报头对象,*data 指针继续向前偏移 8 个字节,用于存储报头数据。这就是 UDP 封装。

    而 UDP 层可能积攒了很多的报文数据,只需要通过 struct sk_buff *next 字段,将报文以链表的形式组织起来。这样一来,对报文的管理,就转变为对链表的增删查改。

  • 更重要的是,不同端的主机通信,采用的也是网络协议栈,同样也有传输层。什么是协议?双方都需要按照同样的规则、同样的标准来通信。因此,在不同端,无论收发信息,采用的都是 udphdr 这样的描述结构体,双方使用同样的数据类型来解释收到的 UDP 报头的 8 个字节。因此协议就是结构化数据,协议就是一种约定。

2.2 UDP的特点

  • 无连接:知道对端的 IP 和端口号就直接进行传输,不需要建立连接。

  • 不可靠:没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息。

  • 面向数据报:不能够灵活的控制读写数据的次数和数量(在向上层交付时,UDP 清楚的报文的有效载荷是多少个字节)。

    应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。

    例如:用UDP传输100个字节的数据,如果发送端调用一次 sendto,发送100个字节,那么接收端也必须调用对应的一次 recvfrom,接收100个字节,而不能循环调用10次 recvfrom,每次接收10个字节。

  • UDP的 socket 既能读,也能写,这个概念叫做全双工。

2.3 UDP的缓冲区及注意事项

  • UDP没有真正意义上的发送缓冲区,调用 sendto 会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。

  • UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致(即可能先发的后收到)。如果缓冲区满了,再到达的UDP数据就会被丢弃。

  • 我们注意到,UDP 协议首部中有一个16位的最大长度,也就是说一个 UDP 能传输的数据最大长度是64K(包含UDP首部)。 然而 64K 在当今的互联网环境下,是一个非常小的数字,如果我们需要传输的数据超过64K,就需要在应用层手动的分包,然后多次发送,并在接收端手动拼接。

3. TCP协议

3.1 报头

在这里插入图片描述

  • 同样的,TCP 报头在内核中也是一种结构化的字段。

  • 4 位首部长度:取值范围 [ 0000 , 1111 ] = [ 0 , 15 ] [0000,1111] = [0, 15] [00001111]=[0,15],单位是 4个字节,即 4 位首部长度实际的取值范围为 [ 0 , 15 ] ∗ 4 = [ 0 , 60 ] [0, 15] * 4 = [0,60] [0,15]4=[060],也就意味着选项字段的大小,最多为 40 40 40 字节。

    假设 TCP 报头的长度为 20 20 20 字节,那么首部长度即为 x ∗ 4 = 20 x * 4 = 20 x4=20 x = 5 x = 5 x=5 ,即 x = 0101 x = 0101 x=0101

    有了首部长度 x x x,默认先读取前 20 20 20 字节,提取首部长度字段,如果 x = 20 x = 20 x=20,即代表报头为 20 20 20 字节;如果 x > 20 x > 20 x>20 x − 20 = x - 20 = x20= 选项字段长度,剩下的就是数据长度。这样一来,即解决了报头和有效载荷的分离问题。

    与 UDP 协议同理,当应用层将数据通过 sendto 传递给传输层后,传输层申请 sk_buff 缓冲区,接着将数据从用户空间拷贝到 sk_buff 缓冲区,再为 TCP 报文构建协议报头并填充字段,最后将报头添加到 sk_buff 缓冲区中。至此,完成对 TCP 报文的封装。

  • 6位标志位(后面详讲):

    • URG: 紧急指针是否有效
    • ACK:确认号是否有效(即应答报文设置的标志位)
    • PSH:提示接收端应用程序立刻从 TCP 缓冲区把数据读走
    • RST:对方要求重新建立连接,我们把携带 RST 标识的称为复位报文段
    • SYN:请求建立连接,我们把携带 SYN标识的称为同步报文段(用于三次握手建立连接)
    • FIN:通知对方,本端要关闭了,我们称携带 FIN 标识的为结束报文段(四次挥手关闭连接)

3.2 流量控制

  • 与 UDP 不同的是,TCP 拥有独立的 发送和接收 缓冲区。并且,单独的客户端既可以同时发送和接收,因此 TCP 是全双工通信。

在这里插入图片描述

  • 假设 TCP 通信的双方,一方发的特别快,另一方处理数据比较慢,但是发送方仍一直持续的发送,那么接收缓冲区就会被写满。但是发送方对于接收缓冲区已经被写满并不知情,所以继续在发送数据,但是数据又存不下了,于是报文被直接丢弃了?

    丢弃后,虽然 TCP 后续可能对该报文进行重传。但是,可能这份报文可能经过无数个路由器,转发了无数次报文,好不容易到才到达目的地,花费这么大的代价,结果被丢弃了??这种做法是不合理的!

    面对上述情况,本质问题就是,发送方无法得知接收方缓冲区的情况。如果接受方来不及接收报文了,发送方 放缓 或 暂停发送,问题就能够得到解决,而这种解决方法称为 流量控制

    在实际 tcp_socket 通信时,我们并没有遇到这类问题,因为上面的工作,已经由发送方的 TCP 完成了,用户并不需要关心,由 TCP 全权负责,这也是为什么 TCP 称为 传输控制协议!在实际的网络通信中,用户层调用 sendto 将数据传递到传输层后,在上层,我们就认为数据已经发送出去了,而实际上,可能数据还存储在本地操作系统的缓冲区内,还未进行发送。

  • TCP 为了保证传输的可靠性,协议要求 TCP 的接收方必须在收到报文后进行确认(向客户端进行响应反馈), 即 确认应答机制

    需要注意的是,假设发送的数据为 " h e l l o " "hello" "hello",真正发送的时候,可不仅仅只有数据,而是将数据封装在报文内,将整个 TCP 报文发送给对方。同样的,接收方在给发送方进行应答时,也是发送的一个 TCP 报文,同时在报头中设置了 ACK 标志位(ACK标志位置 1 1 1)。

  • 16 位窗口大小: 记录发送方接收缓冲区的剩余空间大小。

  • 那么如何进行流量控制呢?? ------ 发送方能够得知接收方的接收能力。

    而接收缓冲区接收能力的强弱,以剩余的空间大小为衡量。因此当接收方在向发送方进行应答时,在应答的报头中的 窗口大小字段,填充自己接收缓冲区的剩余空间大小,那么发送方就能够清楚的进行传输控制了!

    即,窗口大小是用于流量控制的字段!

    上述一切关于流量控制的方式、细节,全部由 TCP 通信的双方的操作系统协商完成!

  • 当接收缓冲区被写满,发送方也就停止发送,但是上层用户可不关心!上层用户还是继续向传输层写写写,那当发送缓冲区也被写满了呢??

    这就是典型的生产消费模型,消费者不消费了,生产者就进行要阻塞!即进程就要进入阻塞状态,其本质就是进程在等待 OS 进行发送。进程是一个执行流,OS 也是一个执行流,这就是两个执行流在进行同步!

    在这里插入图片描述

  • 即便 TCP 是传输具有可靠性的,但也无法保证 100% 可靠的网络通信。

    假设 C 端给 S 端发送第一条信息,但是在这条信息发送出去,到 S 端进行应答之前这段时间,对于 C 端,它是无法确认这次的报文对方是否收到。

    当 S 端给 C 端应答第一条信息后,那么就轮到 S 端无法确认它发出去的报文对方是否收到。那如果要做到 S 端也能够确认自己的报文对方收到了,那就需要 C 端继续发送一次应答,那这次应答的报文,对于 C 端,它又无法确认对方是否收到(因为还没收到对方的应答)。

    所以这个是一个死循环,永远无法确认最新的一条信息对方是否收到了,也即最新的一条消息的可靠性其实是无法保证的。但是!可以保证除了最后一条信息之前的所有信息的可靠性,如上图所示,① 和 ② 都是收到了应答,因此除了最新的 ③ 信息,其它都能够保证可靠性。

2.3 数据发送模式

  • 像我们上面介绍的通信方式,C 端给 S 端发送数据, S 端需要给 C 端进行应答,反之同理。这些都是串行发送的,通信效率比较慢。

    在这里插入图片描述

    这是 TCP 发送数据常见的方式,将发送时间进行重叠,并发的发送多份报文,并且规定每个报文都需要进行应答,保证可靠性的同时提高效率。

  • 由于网络的实际情况错综复杂,因此无法保证接收顺序与发送顺序一致,那么就可能导致数据乱序的问题(可能一份数据拆分为多个报文进行发送),而乱序是不可靠的一种表现,因此在同时发送多份报文的情况下,需要保证报文按序到达。

    即报头内的 32 位序号:给报文携带编号。接收方可以根据报头中序号,对接收到的报文进行排序,即可保证报文按序到达。

  • 还有一个问题是:C 端发了 4 份报文,S 端是需要给 C 端应答 4 次的,那么 S 端的哪一次应答是对 C 端的哪一次报文做的应答呢???如果不能解决这个问题,那么当发送方发了 10 个报文,最终只收到了 9 个应答,那发送方就无法得知,自己发送的 10 个报文里面,到底是哪个报文丢了!导致也无法进行后续补发报文的操作。

    因此报头中还有另一个字段 ----- 32位确认序号:用于记录历史上发送方发送的哪些报文已经被接收方所接收,由接收方在应答报头中填充,对应收到报文的序号值 + 1。

    确认序号之前的所有报文已经被接收方收到。例如:确认序号301代表的含义是序号300 200 100 的报文都已经被 S 端收到了。之所以这样设计的原因是:不管是数据还是应答,在网络传输中都有可能丢失,假设 S 端前三次报文都收到了,但是这三次应答都丢失了,最后一份报文的应答 401 没有丢失,那么 C 端在接收到 S 端的 401 应答时,即可以得知 4 份报文, S 端都接收到了。换言之,这样设计,可以允许少量的应答丢失。

3.4 捎带应答

  • 看似一切完美,在应答的时候明明可以继续用 32 位序号来保障应答的可靠性,为啥还要多设计出一个32位确认序号呢??

    要清楚,我们至始至终,为了方便理解,一直都是以单向通信为例。但实际上的通信是双向的,即 C 端 在向 S 端发数据的同时, S 端 也在给 C 端发数据。

    那么 S 端 就需要在应答 C 端的同时,发送自己的数据。如果只有一个 32 位序号,那么应答 和 发数据 这两件事就需要分开来完成,即 S 端需要向 C 端发送两次报文。而有了 32 位确认序号后,这两件事可以同时完成,即发送数据的同时顺带给 C 端应答了!这就叫做捎带应答!!

    实际通信时,大部分报文都既是数据,又是对历史报文的应答确认!

    总结:TCP 在保证可靠性的同时,还会进行各种提高效率的设定(数据并发发送、捎带应答)!只不过这些工作都有 TCP(内核) 自主完成,用户并不知情。

3.5 URG && 紧急指针

  • 标志位:用于标识不同的报文类型。

    服务器是同时面对多个客户端的,即需要同时处理来自多个客户端的 TCP 报文,而这些报文可能包含连接建立、连接断开、正常数据传输或异常数据等类型。那么服务器就必须具备识别不同报文类型的能力,才能根据报文类型执行相应的处理动作。

  • 我们上面说过,发送方可能同时一次性发送一批报文,并且这批报文的数据是有顺序的,那么就必须保证这批报文按序到达,而按序到达的本质就是队列(先发先收)。但不妨有时候会有一些紧急任务,那么在按序到达的规则下,即便是紧急任务,也要排队!但所谓紧急任务,肯定是需要尽快处理、提前被处理的。

    因此面对这种情况,URG 标志位置 1,表明该报文是紧急报文。

  • 16位紧急指针:记录紧急数据在有效载荷中的偏移量。

    收到报文,先查看标志位,如果 U R G = 1 URG = 1 URG=1,那么根据紧急指针查看紧急数据(紧急数据只有一个字节)。

    紧急任务的场景:假设发送方上传一批数据,但是上传过程中发现上传错了,而此时接收方的缓冲区已经积攒了大量的报文还没被处理,这种情况就可以发送紧急指针,示意对方立即终止或暂停上传行为(通过一些固定的标志信息反馈)(如果直接关闭连接,那么接收方需要把缓冲区的数据全部读取完,才能得知发送方已经关闭连接)。

    再者,例如当发现服务器运行速度比较慢时,通过给服务器发送紧急指针,进行服务检测。

  • 在发送 send 和 接收 recv 的第三个参数 flag,就会提供一些标志位,例如 MSG_OOB 就表示紧急数据。

     ssize_t recv(int sockfd, void *buf, size_t len, int flags);MSG_OOBThis flag requests receipt of out-of-band data that would not be received  in  the  normal  data  stream.
    

3.6 PSH

  • 在讲流量控制的时候,我们讲过,当接受发给发送方应答的同时,报头中的窗口大小会记录接收方缓冲区剩余空间大小,以便发送方进行传输控制。

    假设接收方上层 http 处理数据比较耗时,导致接收缓冲区被写满,随后接收方在应答报文中将窗口大小设置为 0,告知对方无法接收更多数据。一段时间后,接收方的上层处理了一些数据,缓冲区腾出一些空间,但此时的发送方并不知情,还在傻傻的阻塞等待。

    因此,为了避免这种情况,发送方会定期发送空闲时间较长的询问报文(这种方式效率较低,因为它依赖超时来触发询问),然后等待接收方的应答。另一方面,当接收方的缓冲区的剩余空间由 0 0 0 变为 ! 0 !0 !0 时,接收方也会主动向发送方进行窗口大小的更新报文。

  • 这里所谓的询问报文,也是完整的 TCP 报头,同时将 PSH 标志位置 1。即 PSH:告知对方,尽快将数据向上层交付。

    但 PSH 不仅仅应用于询问报文中,当数据需要被尽快交付时,也可以使用。最典型的案例就是,xshell 远程连接远端服务器时,为了保证更好的用户体验,xshell 尽可能的让用户输入的每一条指令携带 PSH 标志位,让上层的 ssh 尽快交付解释。

3.7 RES

  • 我们一直在说通信,但建立 TCP 通信的前提是建立连接,而建立连接就需要三次握手。

    虽然 TCP 是保证可靠性的,但不代表三次握手就必须是成功的,也可能是失败的!保证的不是数据 100% 到达目的地,而是数据到达目的地了 或者 数据传输异常了,TCP 需要知道。

    在这里插入图片描述

  • 三个报文的前两个报文丢失都不影响,假设客户端连接建立请求的报文丢失了,服务端没有收到(服务端知情),那么也就不会给应答。客户端收不到服务端的应答,也就同样知情报文丢了(要么是自己的,要么是对方的应答报文),那么客户端就会进行报文重发。而假设服务端的报文丢了,虽然服务端自己不知情,但是客户端没收到,客户端是知情的,它就不会给服务端发送应答报文,那么服务端收不到应答报文,服务端也知情了。

    最麻烦的是最后一次 ACK,假设最后一次客户端的 ACK 丢了,但客户端并不知情。站在客户端的角度,客户端认为,最后一次 ACK 报文发送出去即连接建立成功,而服务端需要等到接收了报文才认为连接建立成功。这种情况就会导致双端连接建立认知不一致的问题。

    因为客户端认为连接建立好了,所以它就开始向服务端发送数据,服务端收到数据后,脑袋大大的问号,因为它认为三次握手还没完成,于是服务端就向客户端推送一个报文,并在报头中设置 RST 标志位。客户端收到 RST 标志位的报文后,就重置连接,重新开始三次握手。

  • 因此,三次握手的最后一次,是无法保证可靠性的,即三次握手不是一定成功的,但可以通过 RST 标志位做容错处理。

    同样的, RST 也不仅仅应用于三次握手。例如当双方通信的过程中,客户端网络中断,连接被释放了。随后客户端恢复了网络环境,但服务端并不知道,于是继续向客户端发送数据。这也是双端连接建立认知不一致的情况。客户端恢复网络后,它认为连接还没建立,但服务器不知情,依旧认为连接还在。这种情况,客户端同样可以向服务器发送 RST 重置连接请求。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Spring Framework实战》2:Spring快速入门

欢迎观看《Spring Framework实战》视频教程 Spring快速入门 目录 1. Java™开发套件(JDK) 2. 集成开发人员环境(IDE) 3. 安装Maven 4. Spring快速入门 4.1. 开始一个新的Spring Boot项目 4.2. 添加您的代码 4.3. 尝…

利用Deeplearning4j进行 图像识别

目录 图像识别简介 神经网络 感知器 前馈神经网络 自动编码器 受限玻尔兹曼机 深度卷积网络 理解图像内容以及图像含义方面,计算机遇到了很大困难。本章先介绍计算机理解图像教育方面 遇到的难题,接着重点讲解一个基于深度学习的解决方法。我们会…

PTA DS 基础实验3-2.1 一元多项式求导

基础实验3-2.1 一元多项式求导 分数 20 全屏浏览 切换布局 作者 DS课程组 单位 浙江大学 设计函数求一元多项式的导数。 输入格式: 以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。 注意&#xff1a…

vue elementUI Plus实现拖拽流程图,不引入插件,纯手写实现。

vue elementUI Plus实现拖拽流程图,不引入插件,纯手写实现。 1.设计思路:2.设计细节3.详细代码实现 1.设计思路: 左侧button列表是要拖拽的组件。中间是拖拽后的流程图。右侧是拖拽后的数据列表。 我们拖动左侧组件放入中间的流…

DC系列之DC-8渗透测试

DC-8 靶机渗透测试实战 靶机下载地址: https://download.vulnhub.com/dc/DC-8.zip(下载速度慢可以用迅雷下载) 一、实验环境 实验环境: kali2024:192.168.234.145(nat模式) 靶机环境DC-7&#…

matlab中高精度计算函数vpa与非厄米矩阵本征值的求解

clear;clc;close all tic %并行设置% delete(gcp(nocreate));%关闭之前的并行 cparcluster(local); c.NumWorkers50;%手动设置线程数(否则默认最大线程为12) parpool(c, c.NumWorkers); %并行设置%w1; u2.5;N30;valstozeros(2*N2,100); v10linspace(-3,3,100).;parfor jj1:leng…

GraphRAG vs 传统 RAG:如何通过知识图谱提升 AI 检索能力

相比传统 RAG 仅能独立检索文本片段的局限性,GraphRAG通过构建实体关系图谱实现了信息间的连接,让 AI 能更完整地理解和检索复杂的关联信息,从而生成更准确和连贯的回答 问题背景: 想象有一本详细记录某人(X)成就的传记,每个章节都描述了他的…

Pentaho Kettle迁移至Oracle的空字符串和NULL的问题处理,大坑!

一、问题说明 在使用 Kettle 将 DB2 数据迁移到 Oracle 的过程中,出现了 DB2 中为空字符串的字段,在插入到 Oracle 过程中实际插入的为 NULL ,导致触发了非空校验而迁移失败 空字符串 ‘’ ,即长度为0的字符串 搜索该问题后得知…

2025-01-04 Unity插件 YodaSheet1 —— 插件介绍

文章目录 1 介绍2 工作原理2.1 ScriptableObject -> YadeSheetData2.2 YadeDatabase 存储多个 YadeSheetData 3 用途4 缺点5 推荐 1 介绍 ​ Yade 提供类似于 Excel 或者 Google Sheets 的表格编辑器,可以轻松地在 Unity 编辑器中 编辑,搜索&#xf…

VScode 格式化代码空格记录

点击 -> “文件” -> “首选项" -> “设置” -> 按下图操作: 怎么格式化代码空格,先看下: 保存代码后,这代码自动格式化发,如下图: 你可以试试看就即可

苹果系统MacOS下ObjectC建立的App程序访问opencv加载图片程序

前言 苹果系统下使用opencv感觉还是有些不太方便,总是感觉有点受到限制。本博客描述的是在MacOS下建立App程序然后调用opencv显示图片时出现的一些问题并最后解决的一个过程。 一、程序的建立 选择程序的类型: 选择界面模式和编程语言: 其余…

CSS3——3. 书写格式二

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head><body><!--css书写&#xff1a;--><!--1. 属性名:属性值--><!--2.属性值是对属性的相关描述--><!--3.属性名必须是…

windows配置jdk

进入此网址 JDK 11 Releases 找到11版本进行下载 下载好后配置环境变量 按windows加r键输入sysdm.cpl点击确定 在系统变量里新建输入 JAVA_HOME D:\openjdk-1128_windows-x64_bin\jdk-11 //变量值为安装jidk的路径 配置path环境变量 编辑path变量输入%JAVA_HOME%\bin并放置最…

深入刨析数据结构之排序(下)

目录 1.内部排序 1.5选择排序 1.5.1简单选择排序 1.5.2树形选择排序 1.6堆排序 1.7归并排序 1.7.1递归归并 1.7.2非递归归并 1.8计数排序 1.9基数排序 常见内部排序的总结&#xff1a; 1.内部排序 1.5选择排序 选择排序&#xff08;Selection Sort&#xff09;的基…

RocketMQ场景问题

1.消息丢失 有这么一个场景&#xff0c;就是订单支付完成之后&#xff0c;订单系统会进行发送消息给RocketMQ集群&#xff0c;下游会有积分系统进行监听这个消息&#xff0c;进行消费然后给用户发放积分。在下面的这个场景中&#xff0c;通过查询日志发现了订单系统发送订单支付…

cordova项目环境搭建 hello

环境准备&#xff1a; 1.下载nodejs并安装配置。 直接官网下载最新版本。此次我是下载的 Node.js v22.12.0。 1.1安装好后配置镜像。 输入&#xff1a;node -v // 显示node.js版本 npm -v // 显示npm版本 1.2环境配置 &#xff08;1&#xff09;找到安装的目录&am…

LE Audio 初探

LE Audio 架构 一.LE Audio profile框架 profile初识&#xff1a; BAP&#xff1a; BAP通常在手机端实现&#xff0c;它允许配置编解码器&#xff0c;配置QoS(质量服务)&#xff0c;控制流媒体&#xff0c; PACS&#xff1a; Published Audio Capabilities Service&#xff0c;…

Ⅱ.INTRODUCTION TO CUDA C

前言 上一节环境配置好了&#xff0c;我们开始吧&#xff01; 一、A First Program 1. Hello, World! 我们先写一个C语言的 Hello, World! 作为对比 int main(void){printf("Hello, World!\n");return 0; }大家应该知道这个代码运行在CPU上吧&#xff0c;我们CP…

域上的多项式环,整除,相通,互质

例1.已知 (R,,x)为域&#xff0c;请选出正确的说法:(A)(R,,x)也是整区; ABCD (B)R中无零因子; C)R在x运算上满足第一、二、三指数律; (D)R只有平凡理想; (E)R只有平凡子环。 域的特征&#xff1a; 域中&#xff0c;非0元素的加法周期 思考、在模7整数环R,中&#xff0c;…

【0x0014】HCI_Read_Local_Name命令详解

目录 一、命令概述 二、命令格式 三、返回事件及参数说明 3.1. HCI_Command_Complete 事件 3.2. Status 3.3. Local_Name 四、命令执行流程 4.1. 命令发送 4.2. 控制器接收并处理命令 4.3. 控制器返回结果 4.4. 主机接收并解析事件包 4.5. 示例代码 五、应用场景 …