udp tcp协议

文章目录

  • 1. UDP协议
    • 1.1 端口号
    • 1.2 UDP协议格式
    • 1.3 UDP特性
    • 1.4 报文的封装
  • 2. TCP协议
    • 2.1 TCP协议格式
    • 2.2 TCP策略
      • 2.2.1 确认应答机制(ACK)
        • 序号与确认序号
        • 6个标志位
        • 序号的理解
      • 2.2.2 超时重传机制
      • 2.2.3 连接管理机制
        • 三次握手
        • 四次挥手
        • 理解三次握手
        • 理解四次挥手
      • 2.2.4 流量控制
      • 2.2.5 滑动窗口
      • 2.2.6 拥塞控制
      • 2.2.7 延迟、捎带应答
    • 2.3 面向字节流
    • 2.4 粘包问题
  • 3. TCP全连接队列
    • 3.1 backlog
    • 3.2 全连接队列的原理
  • 4. `tcpdump`

1. UDP协议

1.1 端口号

在前面的文章中说过,每一个要网络通信的进程,都要绑定IP地址和端口号

其中端口号划分为两部分:

  1. 0~1023:一些知名协议已经绑定了的端口号
  2. 1024~65535:OS随机分配的端口号

在OS内部,端口号与进程之间的关系类似于哈希表,通过键值port能找到唯一的进程与之对应

在这里插入图片描述

同时,也能说明,一个进程能够绑定多个端口号,但一个端口号只能被一个进程绑定

1.2 UDP协议格式

在这里插入图片描述

  1. 如何将报头与有效载荷分离?

    UDP报头字段固定8字节,读取其中的16位UD长度,减去8字节就是有效载荷的长度

  2. 如何分用?

    根据报头中的16位目的端口号将有效载荷向上层交付

1.3 UDP特性

  1. 无连接
  2. 不可靠
  3. 面向数据报

无连接,在socket编程章节中已有所体现,使用udp通信的双方创建好套接字就能直接通信

而对于不可靠这一特性,讲完tcp的可靠性,自然也就懂了

所谓面向数据报,发送方发多少,接收方就接多少,不能灵活控制发送和接受的次数

udp注意事项:udp没有发送缓冲区,调用sendto直接由内核发送,但有接受缓冲区;udp报头字段中的16位长度表明udp最大长度是64KB,如果发送的数据超过64KB,则需要分批发送

1.4 报文的封装

所谓的报头,在内核中其实就是结构体字段

在这里插入图片描述

在应用层,由于双方操作系统、机器大小端、计算机语言等的不同,发送的数据需要先进行序列化

而传输层属于内核,内核的部分双方几乎一样,都是用C写的,进行序列化再传输反而增加了传输量

因此,横向来看,udp报头是以结构体直接发送的

纵向来看,在OS中,可能同时存在各种各样的报文,有准备向上交付的,有准备向下交付的,有要丢弃的…那么OS就需要对这些报文进行管理 ----- 先描述,再组织;所以,报文的本质也是一个内核数据结构,它有非常多的属性,其中我们重点了解两个指针

在这里插入图片描述

当应用层向下交付时,数据存放在内核中的一段内存上,该内存前面预留了一些空间

最开始,sk_buff中的headdata都指向数据的起始位置

当要封装udp报头时,head向前移动udp报文长度个字节,并赋好值,这样就完成了报文的封装,往下依旧如此

在这里插入图片描述

2. TCP协议

2.1 TCP协议格式

在这里插入图片描述

  1. 如何将有效载荷与报头分离?

    tcp协议格式中的4位首部长度,每bit位表示4字节,总共能表示[0, 60]字节

    tcp协议格式前20字节固定,取出后,拿4位首部长度 - 20字节就是选项,剩余的就是数据

  2. 如何分用?

    接收方根据16位目的端口号向上交付

2.2 TCP策略

我们知道,tcp协议是可靠的、面向连接的,那么tcp是如何保证可靠性,如何连接的呢?这与tcp策略息息相关

2.2.1 确认应答机制(ACK)

发送方发送的报文,可能在传输的过程中丢了,也可能对方收到了,那发送方如何得知报文究竟是丢了还是对方收到了?

很简单,如果对方收到报文,只要给我个应答,就证明我之前发送的数据对方一定收到了;相反,如果我没收到应答,则证明我发送的报文对方没收到

在这里插入图片描述

但是又有问题了,S怎么得知应答对方一定收到了呢?在这里,我们规定,不对应答进行应答,因为如果对应答进行应答,就会无限套下去,C又怎么得知自己的应答对方一定收到…

因此,对于应答,我们无法保证可靠性,但只要收到应答,历史发送的数据对方一定收到;而如果没收到应答,不管是报文丢失,还是应答丢失,发送方就认为对方没收到报文

所谓可靠性,指的是对方收到报文了,我能知道,对方没收到报文,我也能知道

我们把这种确认应答机制也叫做ACK机制,当进行应答时,需要将tcp报头字段中的ACK标志位置1,双方都采用ACK机制,就能保证数据传输的可靠性

序号与确认序号

tcp有两种通信模式,一种是向上述那样,发送一个报文,回一个应答

但更常用的则是:发送方可以一次发送多个报文,接收方在接收到报文后分别对每个报文进行应答,从而提高通信效率

在这里插入图片描述

那么接收方对每个报文应答后,发送方如何确认哪个应答对于哪个报文呢?这就需要tcp报头中的序号与确认序号

当发送方发送报文时,需要对该报文填写唯一性标识 ---- 序号,当接受方收到报文进行应答时,填写确认序号,其中确认序号 = 序号 + 1

在这里插入图片描述

其中确认序号的含义是:+1之前的数据已经全部收到,下次从+1的数据开始发

比如当发送方发送序号为2000的报文,接收方应答时确认序号填写2001,如果接收方收到应答,则认为2000之前的数据对方已经全部收到,下次从2001开始发

同时,如果应答部分丢失,只要收到最近一次报文的应答,就认为之前的报文对方一定收到,因此,该做法允许部分应答丢失

在这里插入图片描述

从上述例子看,貌似tcp只需要一个序号也能对每个发送的报文进行确认,当发送时,填写序号,应答时,将序号当作确认序号来填,不也ok吗?为什么要以序号 + 确认序号的方式?

当发送方发送报文时,对方进行应答的同时,也想发送数据,此时为了提高通信效率,接收方将ACK与要发送的数据作为一个报文,将ACK标志位置1 + 填写确认序号表示应答,填写序号 + 数据表示要发送的数据;在这种情况,就需要序号 + 确认序号

在这里插入图片描述

6个标志位

udp协议中我们说过,OS内有各种各样的报文,在tcp这里更是如此,有应答报文、还有后面讲的发起连接的报文、断开连接的报文等等

因此,OS要对它们进行管理的同时,还要能够对它们进行区分,如何区分报文?根据tcp报头中的6个标志位

在这里插入图片描述

序号的理解

根据我们学过的知识,应用层调用sendto,本质是将数据拷贝到发送缓冲区,在这里,我们不妨将缓冲区看作字符数组,于是每一字节就天然的有一下标,序号的本质就是发送缓冲区数组的下标

在这里插入图片描述

当确认序号为1001时,表示1000之前的数据已经收到,下次从下标为1001的位置开始发

2.2.2 超时重传机制

当发送方发送报文,在一段时间以内,没有收到应答,此时就认为报文丢失,会重新发送报文,我们把这种机制叫做超时重传机制

在这里插入图片描述

那么超时时间应该是多少呢?由于报文是经过网络传输的,而网络的状态是浮动的,有时好,有时坏,当网络好时,超时时间应该短点,以提高效率,但网络坏时,超时时间应该长些,因此,超时时间也应当是浮动

一般来说,linux下的超时时间起初是500ms,第二次发送没收到应答时,超时时间变为2 * 500ms,以此类推,如果连续多次超时重传后还是无法收到应答,则关闭连接

没有收到应答的原因可能是报文丢失,也可能是应答丢失,如果是应答丢失,表明对方收到报文,如果重新发送报文,且对方收到,此时对方的OS内就有两份相同的报文;OS会根据序号来判断两份报文是否相同,如果相同,则丢弃新报文的并给出应答

tcp通信模式中,常见的是第二种,多个报文一并发送时,由于报文是经过网络传输的,它们走的线路不同,到达对方主机的时间也就不同,也就意味着发送的报文可能是有序的,但接受时可能是无序的,此时,OS会根据报文的序号来排序,确保向上层交付的数据是有序的

总上来看,序号的作用主要有3点:

  1. 对发送的报文进行唯一性确认
  2. 对报文进行去重
  3. 使报文按序到达

2.2.3 连接管理机制

三次握手

我们总是tcp是面向连接的,那么它是如何建立连接的?

使用tcp协议通信的双方,在通信之前需要建立连接,通常由client发起连接

当server调用listen后,进入LISTEN状态,client调用connect,发起连接,连接报文中不能携带数据,将SYN标志位置1,表示是连接报文,询问sever,我要和你建立连接,你是否同意

server收到报文后,同意建立连接的同时,反问client,我同意你到我的一个连接,但我也要和你建立连接,你是否同意

client收到报文后,同意server到client的连接

在这里插入图片描述

在上述过程中,client发起SYN,收到SYN + ACK,发送ACK,总共收发3个报文;server收SYN,发SYN + ACK,收ACK,也总共收发3个报文

我们把上述建立连接的过程叫做tcp的三次握手

那么问题来了,如果client发出的最后一个ACK丢失了呢,由于无法保证应答的可靠性,不就代表连接建立失败了吗?事实上,的确如此,所以建立建立的本质就是在赌最后一个ACK对方一定收到

那如果最后一个ACK就是丢了呢?其实也是有办法的,要注意,对于client,在发送最后一个ACK时,它到server的连接已经建立好

但对于server,只有收到ACK时,它到client的连接才建立好

也就是说client->server的连接与server->client的连接建立好之间,有一段时间间隔

在这段间隔之内,也就是server->client的连接建立好之前,client有可能已经给server发送了数据报文,如果最后一个ACK丢了,而server又收到了client发送的数据报文,此时server判断自身连接还没建立,就会给client发送一个将RST标志位置1的报文,表示异常连接,要求client重新建立连接,client收到后,就会断开连接,重新发起三次握手

不仅仅是上述示例中,在通信的任何时刻,只要发现tcp连接异常,都可以向对方发送RST标志位置1的报文,重新建立连接

四次挥手

建立连接后,双方正常通信,突然client不想通信了,关闭了文件描述符,于是发起断开连接的报文 — 将FIN标志位置1,询问对方,我想和你断开连接,你是否同意,server同意了,给了应答

过会,server也不想和client通信了,于是也关闭文件描述符,发起断开连接的报文,server要client断开连接,问client是否同意,client也同意,至此,双方的连接彻底断开

同理,client和server收发报文各自总共4次,我们也把双方断开连接的过程叫做tcp四次挥手

在这里插入图片描述

在这里,又有几个问题

  1. 根据上文说的,能不能将server发给client的ACK与server要与client断开连接FIN报文合并?

    不能,一方想要与对方断开连接,原因是我要发给对方的数据已经发完了,所以我要和对方断开连接,但对方要给我发送的数据不一定发完

    因此,client发送的数据发完,就和对方断开连接,此时server仍可能要给client发送数据,等到server的数据发完,由server自主发起断开连接

    这也是为什么断开连接叫四次挥手

  2. 根据现有的知识,一个fd对应一个连接,一个连接在传输层对应两个缓冲区,发送和接受缓冲区,既然client已经关闭fd了,也就是销毁发送和接受缓冲区了,为什么还能接受server发来的数据?

    这里的close(),我们可以理解为shutdown(sockfd, SHUT_WR),也就是只关闭了发送缓冲区,等到双方的连接都断开,才是真正的close()

需要注意的是,client应答ACK后,到server收到应答,需要一段时间,这也是为什么之前我们写tcp服务器时,关闭服务器后又立马重启发现绑定端口号错误的原因,只要没收到应答,连接就还在,端口号就还在被占用,也就绑定失败了

理解三次握手

建立连接,为什么是三次握手?

在OS内,连接有很多种,有正在三次握手的连接、正在四次挥手的连接、正常通信的连接…OS需要对这些连接管理 — 先描述,再组织,连接在OS内本质也是内核数据结构,需要花费空间创建结构体对象,花费时间管理,这意味着管理连接是需要成本的

首先,来看一次和两次为什么不行,一次不用说了,SYN报文的可靠性都不能保证;而两次中,client发送SYN,server收到应答就建立好连接,由于建立连接的成本太低,client可以向server发送大量建立连接的报文,而server对每个连接都默认接受,导致server承受过重压力,可能会引发SYN洪水问题

而三次握手,虽然也可能存在SYN洪水的问题,但最重要的是:

  1. 验证了双方网络的连通性
  2. 以最小的成本建立双方通信的共识

client能收、能发,client->server网络正常,server也能收、能发,server->client网络正常,双方网络连通

client想和server通信,server同意了,server也想和client通信,client同意了,双方达成共识

以上两点,一次两次握手都达不到,因此,这才是为什么tcp建立连接是三次握手的原因

理解四次挥手

实际上,跟三次握手同理,四次挥手之所以叫做四次挥手,在于它以最小的成本建立双方断开连接的共识

根据我们四次挥手图的理解,对方在收到建立连接的报文后,如果不关闭fd,会处于CLOSE_WAIT的状态;同时,主动断开连接的一方,在收到对方断开连接的报文后,会处于TIME_WAIT的状态,下面我们来验证

我们拿tcp_echo_server来验证

在这里插入图片描述

在这里插入图片描述

那么主动断开连接的一方为什么最后要处于TIME_WAIT的状态?

该状态维持多长时间?

能不能不处于该状态,好让下次服务器直接重启?

报文是经过网络传输的,当断开连接时,报文可能还在传输的路上,如果连接直接断开,又立马重启了,这时就可能收到上次在网络中遗留的报文,影响到了本次通信,因此,处于TIME_WAIT 的状态就是为了等待这些报文到达后,将它们丢弃;也有另一个原因,就是最后一个ACK,server不一定收到,超时时间后,server会再次发送FIN,此时client还没退出,就能再ACK,确保server也能退出

处于TIME_WAIT的状态的时长一般是2 * MST,这里的MST是报文的最大生存时间,根据操作系统而变

cat /proc/sys/net/ipv4/tcp_fin_timeout # 查看当前系统的MST

在这里插入图片描述

要想client退出后,不进入TIME_WAIT状态,将server的listensockfd设置以下即可

在这里插入图片描述

在这里插入图片描述

2.2.4 流量控制

在这里插入图片描述

应用层调用write,将数据拷贝到发送缓冲区,由tcp控制数据的传输;如果对方的接受缓冲区满了,那么到达的报文也就直接丢弃了,这种做法虽然可行,但却不合理,报文的传输消耗了网络资源,CPU等硬件资源,却就这样被丢弃

因此,tcp在传输数据时,应该要考虑对方的接受能力,根据对方接受能力的大小来控制数据应该发多少,我们把这种策略叫做流量控制

所谓对方的接受能力,实际就是对方接受缓冲区剩余空间的大小

那么,发送方该如何得知对方的接受能力呢?

这就引入tcp报头字段中的"16位窗口大小"了,在对报文应答时,不仅要将ACK标志位置1,有数据的加数据,还要将自身发送缓冲区剩余空间的大小填入16位窗口大小中,这样,对方在收到ACK时,就能得知我当前的接受能力

tcp报文字段中的选项中,可能会有窗口扩大因子的选项,实际的窗口大小 = 窗口大小 << 窗口扩大因子

实际上,在tcp三次握手时,双方就是在告知对方自身最初的接受能力

在极端情况下,对方的接受能力为0,此时发送方停止发送数据,对方也就不ACK了,对方的接受能力也就无从得知了,此时如何判断对方有接受能力了,从而继续发送数据?

一方面,接收方会时不时的发送窗口更新通知的报文,主动告知自身的接受能力;另一方面,发送方也会时不时的发送窗口探测报文,对方只要ACK,就能得知其接受能力

那如果对方的接受能力仍然是0呢?发送方可以发送PSH标志位置1的报文给对方,提醒对方尽快将缓冲区里的数据向上交付;任何时候,只要希望数据尽快向上交付,都能将PSH标志位置1

至此,还剩一个URG标志位,它通常配合16紧急指针使用,为1表示紧急指针有效,否则无效;紧急指针实际是一个偏移量,指向接受缓冲区中某1字节;有时,我们给对方发送数据,在某一时刻希望取消发送数据,于是发送URG标志位置1的报文,但如果接收方依旧按序接受报文,当读到URG标志位,前面的报文已经处理完毕,又要撤回,相当于前面的工作白做了;因此,tcp提供了某些报文"插队"的做法,一般两个进程,一个正常读取,一个快速读取URG标志位,如果为1,则告知另一个进程取消读取

2.2.5 滑动窗口

前面我们介绍了超时重传机制和流量控制,但仍有问题:

  1. 已经发送的报文,在接受到ACK之前或者超时重传时间之内,不能被丢弃,需要保存起来,保存在哪?
  2. 通过窗口大小已经得知对方的接受能力,如何根据对方的接受能力进行数据的发送呢?

为了解决上述问题,tcp引入滑动窗口的概念,规定,在滑动窗口以内的数据可以直接发送,暂时可以不做应答

所谓的滑动窗口,实际就是发送缓冲区的一段区域,于是,滑动窗口将发送缓冲区分成三部分

在这里插入图片描述

到这里,我们可以粗略的将滑动窗口定义为:滑动窗口 = 对方的接受能力(对方接受缓冲区剩余空间的大小)

于是,我们根据滑动窗口的定义,来判断下面的问题:

  1. 滑动窗口能不能向左移动?

    已发送,已应答的数据无需再发送,因此滑动窗口只能向右移动,不能向左

  2. 滑动窗口能不能变大?变小?为0?

    滑动窗口 = 对方的接受能力,对方应用层调用read,接受能力就变大了,滑动窗口也就变大了;同理,滑动窗口也能变小,甚至为0

又根据之前的知识,缓冲区可以认为是一个字符数组,我们进一步将滑动窗口精细化的描述

滑动窗口本质是数组中的两个下标

在这里插入图片描述

现在,我们已经知道滑动窗口的具体含义了,可以根据滑动窗口来进行数据的发送了

那么问题来了,如果发送的报文丢了呢?

在这里插入图片描述

在这里插入图片描述

拿上图举例,如果最左边报文丢失,接收方在对其他报文进行应答时,根据确认序号的定义,只能填0,因为1000的报文没收到,当发送方收到3个以上的相同应答,触发快重传机制,立即补发1000的报文,接收方可以直接ACK4001,表示4000之间的报文已经收到

对应滑动窗口,win_start不动

如果是中间报文丢失,接收方ACK确认需要填1001,win_start右移,此时问题变成最左边报文丢失

最右边报文丢失同理,最终变成最左边报文丢失问题

上面提到的快重传机制与超时重传机制有何不同?

快重传是连续收到3个以上同样的应答所触发;如果在通信末期,可能报文丢失,但收不到3个以上的同样的应答,此时超时重传能进行报文的补发;可以说,超时重传是为报文的可靠性兜底的

如果是ACK丢失呢?这点我们之前说过,允许ACK丢失,只要收到最后的ACK,就能保证前面的数据对方收到了

因此,重新看待最开始的两个问题,收到ACK之前,报文保存在哪?---- 滑动窗口中;如何根据对方的接受能力控制数据的发送—滑动窗口内的数据就是能直接发送给对方的数据

2.2.6 拥塞控制

报文是经过网络传输的,网络有时好,有时坏;因此,有时报文的丢失可能是因为网络的原因

如何得知报文的丢失是因为网络的原因还是对方主机的原因呢?

如果发送100报文,其中小部分丢失,则判断网络状况正常,而如果大部分都丢失了,则认为是网络的原因,网络出现了拥塞问题

一旦网络出现拥塞问题,就要降低发送报文的数量,由于所有主机传输数据都遵循tcp协议,因此当网络出现拥塞,所有主机都能降低报文发送的数量,解决拥塞问题的关键在于,所有主机都有拥塞避免的共识

tcp引入拥塞窗口,它的含义是导致网络拥塞的最大报文数量

因此,在最开始,我们发送报文的数量不能超过导致网络拥塞的报文数量,滑动窗口 = min(对方的接受能力,拥塞窗口)

由于网络是浮动的,拥塞窗口也应当浮动,如何得知当前网络的拥塞窗口?一定需要多次探测

为什么拥塞窗口,tcp采用慢启动机制,采用2^n的数学模型来控制报文数量

在这里插入图片描述

采用2^n的好处是,一开始,报文数量少,能慢慢增加报文的数量,等待网络恢复;一旦网络恢复,因其增幅快的特性,能快速进入正常通信

但也不能一味的增长,我们需要准确探测到当前的拥塞窗口,当以2^n增长到某一阈值时,改为线性探测,知道导致网络拥塞,将新的阈值改为拥塞窗口的一半,继续采用慢启动机制…

2.2.7 延迟、捎带应答

当接受方接受到报文时,并不会立马做应答,而是会延迟一段时间,在这段时间内,应用层可能将数据取走,这样就能给发送方一个更大的窗口大小,以提高通信效率,我们把这种策略叫做延迟应答

而捎带应答,我们之间也见过,当给对方应答时,也想发送数据,就能把ACK和数据一并发送,tcp三次握手就是做了捎带应答

2.3 面向字节流

对于udp,发送方发的,就是接收方收的,不能灵活控制发送次数和接受次数

对于tcp,发送方可以多次发送,接收方也能分多次接受 — 面向字节流

2.4 粘包问题

对于tcp,接收方收到报文将数据放到接受缓冲区,对于应用层来讲,数据全是字符串,也就是各种数据黏在一起,怎么区分一个完整的数据 — 序列化与反序列化

3. TCP全连接队列

3.1 backlog

为了解释listen的第二个参数backlog具体有何作用,将服务器不对任何连接accept,并设置backlog为2,将3个client与server连接

在这里插入图片描述

确实存在三个client->server的连接,三个server->client的连接,同时也证明accept不参与三次握手的过程

当再有client连接时

在这里插入图片描述

client->server连接处于SYN_SENT的状态,这表示SYN报文已经发出,但server没同意建立连接,同时没有server->client的连接

当sever来不及accept时,允许client与server继续建立连接,但最多只能有 backlog + 1个连接

在OS中,来不及accept的连接会以队列的方式管理起来,我们把管理这些连接的队列叫做全连接队列

3.2 全连接队列的原理

在这里插入图片描述

需要注意的是,不是指服务器只能接受backlog + 1个连接,而是来不及接受的连接最多只能是backlog + 1个

backlog的值不建议太大,也不能为0,如果太大,后面的连接就需要等待较长时间,如果为0,等待server需要accept连接时,还需要继续三次握手

当前server来不及accept,等待空闲了,直接从全连接队列中拿,本质是减少了服务器的闲置率,提高用户的体验

从内核层面,我们理解连接

在这里插入图片描述

4. tcpdump

sudo tcpdump -i any      # 捕获任意报文
sudo tcpdump -i any tcp  # 捕获任意tcp报文sudo tcpdump -i eth0 tcp # 捕获指定网络接口的tcp报文sudo tcpdump src host xxx and tcp # 捕获指定源ip的tcp报文
sudo tcpdump src host xxx and dst host xxx and tcp # 捕获指定源ip和目的ip的tcp报文sudo tcpdump port xxx and tcp # 捕获指定端口的tcp报文sudo tcpdump -n port xxx and tcp -w xxx.pcap # 将捕获的tcp报文写到文件中
sudo tcpdump -r xxx.pcap # 将文件中的报文信息显示

在这里插入图片描述

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

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

相关文章

【C++ 基础】从C到C++有哪些变化

C到C C相比C语言来说&#xff0c;多了两个核心&#xff0c;五个内容&#xff1a;1、面向对象的思维&#xff1b;2、模板&#xff08;泛型编型&#xff09;1.bool 2.引用 3.内联 4.重载 5.缺省参数变量 数据类型 bool 布尔 占1个字节 取值&#xff1a;true false bool isMax(i…

提高保养效率:4S店预约系统的设计与开发

3.1可行性分析 开发者在进行开发系统之前&#xff0c;都需要进行可行性分析&#xff0c;保证该系统能够被成功开发出来。 3.1.1技术可行性 开发该4S店预约保养系统所采用的技术是vue和MYSQL数据库。计算机专业的学生在学校期间已经比较系统的学习了很多编程方面的知识&#xff…

支付域——支付路由设计

摘要 本文深入探讨了支付路由系统的背景、核心作用、设计原则以及业界常见形态。文章详细解析了支付方式咨询、渠道咨询和渠道路由的概念&#xff0c;并介绍了支付路由的规则种类、交易参数、通道属性和常见筛选规则。进一步讨论了基于规则的渠道路由设计、自动化开关的渠道路…

TORCH_CUDA_ARCH_LIST

目录 查看方法&#xff1a; 设置方法&#xff1a; 查看方法&#xff1a; python -c "import torch; print(torch.cuda.get_device_capability())" 设置方法&#xff1a; 通过代码设置&#xff1a; 在你的 Python 脚本中&#xff0c;使用 os.environ 来设置 TORCH_…

WebAuthn 项目常见问题解决方案

WebAuthn 项目常见问题解决方案 webauthn Webauthn / passkeys helper library to make your life easier. Client side, server side and demo included. [这里是图片001] 项目地址: https://gitcode.com/gh_mirrors/webaut/webauthn 项目基础介绍 WebAuthn 项目是一个开源…

leetcode 面试经典 150 题:螺旋矩阵

链接螺旋矩阵题序号54题型二维数组&#xff08;矩阵&#xff09;解题方法模拟路径法难度中等熟练度✅✅✅ 题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3…

【设计模式】空接口

&#xff08;空&#xff09;接口的用法总结 接口用于定义某个类的特定能力或特性。在工作流或任务管理系统中&#xff0c;接口可以帮助标识哪些任务可以在特定阶段执行。通过实现这些接口&#xff0c;任务类可以被标识为在相应的阶段可以执行&#xff0c;从而在验证和执行逻辑…

保护模式基本概念

CPU 架构 RISC&#xff08;Reduced Instruction Set Computer&#xff09; 中文即"精简指令集计算机”。RISC构架的指令格式和长度通常是固定的&#xff08;如ARM是32位的指令&#xff09;、且指令和寻址方式少而简单、大多数指令在一个周期内就可以执行完毕 CISC&…

突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除

GitLab停止为中国大陆、香港和澳门地区提供服务&#xff0c;要求用户在60天内迁移账号&#xff0c;否则将被删除。这一事件即将引起广泛的关注和讨论。以下是对该事件的扩展信息&#xff1a; 1. 背景介绍&#xff1a;GitLab是一家全球知名的软件开发平台&#xff0c;提供代码托…

git Force Push失败:unable to access解决方案

git Force Push失败&#xff1a;unable to access 项目场景&#xff1a;问题描述原因分析&#xff1a;解决方案&#xff1a;1、访问github远程仓库&#xff0c;更新推送规则1、打开代码库&#xff0c;点击settings2、在settings中下翻&#xff0c;在Danger Zone中将点击Disable…

工业相机镜头选型知识详解

工业相机在机器视觉、自动化生产和检测等领域扮演着重要角色&#xff0c;而镜头作为工业相机的关键组件&#xff0c;其选型直接影响到成像效果和系统的整体性能。在本篇博客中&#xff0c;我们将详细讲解工业相机镜头选型的相关知识&#xff0c;帮助您在实际应用中选择最合适的…

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——13使用Resnet-Bin

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——13使用Resnet-Bin ​ 根据前面的内容&#xff0c;目前已经可以获取到resnet的bin模型 1 .Resnet的bin测试 ​ 这里给大家一个测试视频里面黑线的demo&#xff0c;大家可以用来测试自己的黑线识别精度 …

Rust: offset祼指针操作

offset是偏移元素个数&#xff0c;不是字节数&#xff01; fn main(){let student_a Student{id:20240001,name:"张三娃".into(),class_id:3,age:14,grade:1};let student_b Student{id:20240002,name:"李四牛".into(),class_id:3,age:15,grade:1};let …

安装CPU版的torch(清华源)

1、安装指令&#xff1a; pip3 install torch torchvision torchaudio -i https://pypi.tuna.tsinghua.edu.cn/simple2、验证torch是否安装成功 // 使用python验证 import torch print(torch.__version__)能正常打印版本即表示安装成功&#xff0c;如下图

‘pnpm’ 不是内部或外部命令,也不是可运行的程序或批处理文件。

‘pnpm’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 1.情况: npm -v 和 node -v的都正常就是 pnpm-v 无效 检查环境变量也没看出问题 2.分析 没有正确添加环境变量 3.解决 找到npm的全局安装目录 npm list -g --depth 0这里出现了npm的全局安装…

Java 日志类库

Java 日志库是最能体现 Java 库在进化中的渊源关系的&#xff0c;在理解时重点理解日志框架本身和日志门面&#xff0c;以及比较好的时间等。要关注其历史渊源和设计&#xff08;比如桥接&#xff09;&#xff0c;而具体在使用时查询接口即可&#xff0c;否则会陷入 JUL&#x…

了解VC++ OpenGL绘制模型时设置窗口像素格式

最近看到一个源码,可以读取obj格式模型,显示模型;显示的模型如上一篇博文; 它在视类窗口创建的时候,执行如下的一些, int CRenderView::OnCreate(LPCREATESTRUCT lpCreateStruct) {if (CView::OnCreate(lpCreateStruct) == -1)return -1;HWND hWnd = GetSafeHwnd();HDC…

【Rust自学】6.3. 控制流运算符-match

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 6.3.1. 什么是match match允许一个值与一系列模式进行匹配&#xff0c;并执行匹配的模式对应的代码。模式可以是字面值、变量名、通配符等…

聚类之轮廓系数

Silhouette Score&#xff08;轮廓系数&#xff09;是用于评估聚类质量的指标之一。它衡量了数据点与同簇内其他点的相似度以及与最近簇的相似度之间的对比。 公式 对于一个数据点 i&#xff1a; a(i): 数据点 i 到同簇内其他点的平均距离&#xff08;簇内不相似度&#xff…

unity弹出新的类似独立场景窗口独立运行一般怎么实现?

在Unity中实现弹出类似独立场景窗口并独立运行的功能&#xff0c;通常需要采用一些特定的方法或工具&#xff0c;因为Unity本身并没有直接提供这种功能的内置选项。以下是一些可能的实现方法&#xff1a; 1. 使用多个Scene&#xff08;场景&#xff09; 加载新Scene&#xff…