SIP系列七:ICE框架(P2P通话)

        我的音视频/流媒体开源项目(github)

        SIP系列目录

目录

一、NAT

1、NAT介绍

2、NAT类型

2.1、 完全圆锥型NAT

2.2、受限圆锥型NAT

2.3、端口受限圆锥型NAT

2.4、对称NAT

3、NAT打洞

3.1、不同一NAT下

3.2、同一NAT下          

二、ICE

三、ICE中的SDP


        至此,SIP的基础内容都介绍完了,SIP建立连接之后两个SIP用户就可以进行媒体通话了,但是媒体通话是点对点(P2P)的,不经过SIP代理服务器,但是实际上用户的设备(PC,手机等)都没有自己的公网地址,所以两端是不可能直接通信的,除非两个用户都在同一个局域网内部。因此SIP建立通话的过程中要获取对端的公网地址和端口才能进行P2P媒体通话,这里涉及到两个重要的概念:NAT、ICE,下面就对这两个概念进行介绍。

一、NAT

        参考:WebRTC源码研究(25)NAT打洞原理_webrtc 打洞-CSDN博客

1、NAT介绍

        NAT(网络地址转换Network Address Translation),在计算机网络中是一种在IP数据包通过路由器或防火墙时重写来源IP地址或目的IP地址的技术,这种技术被普遍使用在有多台主机但只通过一个公有IP地址访问互联网的私有网络中。NAT解决了IPV4地址短缺和网络安全的问题,但也让主机之间的通信变得复杂,导致了通信效率的降低,因为大家都藏在NAT之后了,无法直接通信。

        以传统的邮件作为例子,给大家说明NAT是什么?比如A和B两个人要发信,那B告诉A它在某个楼的某层时,这个时候A 可以给B发消息或者信件吗?这肯定不行,因为它并不知道一个具体的地址是多少?你必须告诉它具体哪个省哪个市哪个区哪个小区哪号楼哪层时,只有这种公共的地址,也就是大家都认识的地址,邮局才能帮你把这封信送达。你说哪号楼哪层这个只有你小区内的人才知道。那这个就和我们的网络是相关的。对于网络上的主机,你必须要有个公网的地址,那相互之间才能进行通讯,如果告诉它一个私网(内网)的地址,那它根本找不到你。那对于我们现实中大部分主机都是在网关之后的,他们之间都是有自己的内网IP地址,并不知道自己的外网是多少。那怎么办呢?实际是有一个映射,在网关上有个NAT功能,它可以使你的内网地址变成外网地址。所以他就是一个资源组,映射之后就将你的内网IP端口映射成外网IP端口。那有了外网的IP端口之后,其他的主机就可以通过内网的IP地址与你通讯了。这就是NAT。

        如下图所示,表示了NAT的作用:

        左边的分别是内网的几台机子,通过内网的IP他们之间是可以相互通信的,但是与互联网之间是不通的,如何访问互联网的资源呢,就必须通过NAT,将我们的内网地址转换成外网地址。

        RFC1918规定了三个保留地址段落:10.0.0.0-10.255.255.255;172.16.0.0-172.31.255.255;192.168.0.0-192.168.255.255。这三个范围分别处于A,B,C类的地址段,不向特定的用户分配,被IANA作为私有地址保留。这些地址可以在任何组织或企业内部使用,和其他Internet地址的区别就是,仅能在内部使用,不能作为全球路由地址。这就是说,出了组织的管理范围这些地址就不再有意义,无论是作为源地址,还是目的地址。对于一个封闭的组织,如果其网络不连接到Internet,就可以使用这些地址而不用向IANA提出申请,而在内部的路由管理和报文传递方式与其他网络没有差异。

        对于有Internet访问需求而内部又使用私有地址的网络,就要在组织的出口位置部署NAT网关,在报文离开私网进入Internet时,将源IP替换为公网地址,通常是出口设备的接口地址。一个对外的访问请求在到达目标以后,表现为由本组织出口设备发起,因此被请求的服务端可将响应由Internet发回出口网关。出口网关再将目的地址替换为私网的源主机地址,发回内部。这样一次由私网主机向公网服务端的请求和响应就在通信两端均无感知的情况下完成了。依据这种模型,数量庞大的内网主机就不再需要公有IP地址了。

        NAT处理报文有几个关键特点:

        1)网络被分为私网和公网两个部分,NAT网关设置在私网到公网的路由出口位置,双向流量必须都要经过NAT网关;
        2)网络访问只能先由私网侧发起,公网无法主动访问私网主机;
        3)NAT网关在两个访问方向上完成两次地址的转换或翻译,出方向做源信息替换,入方向做目的信息替换;
        4)NAT网关的存在对通信双方是保持透明的;
        5)NAT网关为了实现双向翻译的功能,需要维护一张关联表,把会话的信息保存下来。

        NAT网络地址转换有两种方式:基本网络地址转换(Basic NAT)、网络地址端口转换(NAPT)。

        基本网络地址转换(Basic NAT):

        这一种也可称作NAT或“静态NAT”,在RFC 2663中提供了信息。它在技术上比较简单,仅支持地址转换,不支持端口映射。Basic NAT要求对每一个当前连接都要对应一个公网IP地址,因此要维护一个公网的地址池。宽带(broadband)路由器通常使用这种方式来允许一台指定的设备去管理所有的外部链接,甚至当路由器本身只有一个可用外部IP时也如此,这台路由器有时也被标记为DMZ主机。由于改变了IP源地址,在重新封装数据包时候必须重新计算校验和,网络层以上的只要涉及到IP地址的头部校验和都要重新计算。

        网络地址端口转换(NAPT):

        这种方式支持端口的映射,并允许多台主机共享一个公网IP地址。支持端口转换的NAT又可以分为两类:源地址转换和目的地址转换。前一种情形下发起连接的计算机的IP地址将会被重写,使得内网主机发出的数据包能够到达外网主机。后一种情况下被连接计算机的IP地址将被重写,使得外网主机发出的数据包能够到达内网主机。实际上,以上两种方式通常会一起被使用以支持双向通信。

        NAPT维护一个带有IP以及端口号的NAT表,结构如下:

        基本网络地址转换(Basic NAT)已不常用,我们通常提到的NAT就是NAPT。

        NAT 的副作用主要有下面几点:

  • 对等网络传输需穿透NAT:IP协议的定义中,在理论上,具有IP地址的每个站点在协议层面有相当的获取服务和提供服务的能力,不同的IP地址之间没有差异。但NAT工作原理破坏了这个特征,如需实现真正意义上的对等网络传输,则需要穿透NAT。这是本文重点。
  • 应用层需保持UDP会话连接:由于NAT资源有限,会根据一定规则回收转换出去的资源(即ip/port组合),UDP通信又是无连接的,所以基于UDP的应用层协议在无数据传输、但需要保持连接时需要发包以保持会话不过期,就是通常的heartbeat之类的。
  • 基于IP的访问限制策略复杂化。

        国内移动无线网络运营商在链路上一段时间内没有数据通讯后, 会淘汰NAT表中的对应项, 造成链路中断。

  • NAT带来的第一个副作用:NAT超时:

        国内的运营商一般NAT超时的时间为5分钟,所以通常我们TCP长连接的心跳设置的时间间隔为3-5分钟。

  • NAT带来的第二个副作用就是:NAT墙。

        NAT会有一个机制,所有外界对内网的请求,到达NAT的时候,都会被NAT所丢弃,这样如果我们处于一个NAT设备后面,我们将无法得到任何外界的数据(除非我们主动连接外部设备)。

        但是这种机制有一个解决方案:就是如果我们A主动往B发送一条信息,这样A就在自己的NAT上打了一个B的洞。这样A的这条消息到达B的NAT的时候,虽然被丢掉了,但是如果B这个时候在给A发信息,到达A的NAT的时候,就可以从A之前打的那个洞中,发送给到A手上了。

        简单来讲,就是如果A和B要进行通信,那么得事先A发一条信息给B,B发一条信息给A。这样提前在各自的NAT上打了对方的洞,这样下一次A和B之间就可以进行通信了。

2、NAT类型

        如上图所示,基础型基本不用了,常用的NAPT有图示的四种类型。

2.1、 完全圆锥型NAT

        完全圆锥型NAT(Full cone NAT),即一对一(one-to-one)NAT。

        一旦一个内部地址(iAddr:port)映射到外部地址(eAddr:port),所有发自iAddr:port的包都经由eAddr:port向外发送。任意外部主机都能通过给eAddr:port发包到达iAddr:port(注:port不需要一样),是最好穿越的一种 NAT类型。但是安全性就差很多。

2.2、受限圆锥型NAT

        内部客户端必须首先发送数据包到对方(IP=X.X.X.X),然后才能接收来自X.X.X.X的数据包。在限制方面,唯一的要求是数据包是来自X.X.X.X。
        内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自iAddr:port1的包都经由eAddr:port2向外发送。外部主机(hostAddr:any)能通过给eAddr:port2发包到达iAddr:port1。(注:any指外部主机源端口不受限制,但是目的端口必须是port2。只有外部主机数据包的目的IP 为内部客户端的所映射的外部ip,且目的端口为port2时数据包才被放行。)

        客户端向P发送了数据那么P机器上的所有端口都可以向客户端发送数据,但是别的机器是不可以的,也就是只要IP对就行,端口不管,入下图所示:

2.3、端口受限圆锥型NAT

        类似受限制锥形NAT(Restricted cone NAT),但是还有端口限制。

        需要满足两个条件:客户端主要向外界主机发送消息、外界主机返回的消息的IP和PORT必须和客户端发送的数据包中的相同。如下图所示:

2.4、对称NAT

        前几个类型的NAT,客户端向不同的主机发送消息,NAT都只有一组ip:port映射,在对称NAT中,客户端向不同的主机发送消息,会有不同的ip:port映射。而且外部主机返回消息的ip:port不能变。

        对称NAT特点:和不同主机通信都会有不同的映射,而且ip和端口都要限制。

        对称NAT是最难穿越的,如果两个通信的主机都在对称NAT之后,是不可能穿越的。

3、NAT打洞

        最常用的打洞技术使用的是STUN/TURN协议,是一种UDP的穿透规范。

        首先看一下UDP打洞技术。参考:P2P通信原理与实现 - 有价值炮灰

3.1、不同一NAT下

        假设客户端A和客户端B的地址都是内网地址,且在不同的NAT后面。A、B上运行的P2P应用程序和服务器S都使用了UDP端口1234,A和B分别初始化了 与Server的UDP通信,地址映射如图所示:

        现在假设客户端A打算与客户端B直接建立一个UDP通信会话, 如果A直接给B的公网地址138.76.29.7:31000发送UDP数据,NAT B将很可能会无视进入的 数据(除非是Full Cone NAT),因为源地址和端口与S不匹配,而最初只与S建立过会话.。B往A直接发信息也类似。

        假设A开始给B的公网地址发送UDP数据的同时,给服务器S发送一个中继请求,要求B开始给A的公网地址发送UDP信息。A往B的输出信息会导致NAT A打开 一个A的内网地址与与B的外网地址之间的新通讯会话(此时B向A发送的消息将不再被丢弃),B往A亦然。 一旦新的UDP会话在两个方向都打开之后,客户端A和客户端B就能直接通讯,,而无须再通过引导服务器S了。

3.2、同一NAT下          

        如果A和B在同一个NAT下经过上面的打洞过程,会有如下图所示的结果:

        首先A和B会得到由S观测到的对方的公网IP和端口号,然后给对方的地址发送信息。两个客户端只有在NAT允许内网主机对内网其他主机发起UDP会话的时候才能正常通信,我们把这种情况称之为"回环传输“(loopback transmission),因为从内部 到达NAT的数据会被“回送”到内网中而不是转发到外网。例如:当A发送一个UDP数据包给B的公网地址时,数据包最初有源IP地址和端口地址10.0.0.1:1234和 目的地址155.99.25.11:62001,NAT收到包后,将其转换为源155.99.25.11:62000(A的公网地址)和目的10.1.1.3:1234,然后再转发给B。即便NAT支持 回环传输,这种转换和转发在此情况下也是没必要的,且有可能会增加A与B的对话延时和加重NAT的负担。

        对于这个情况,优化方案是很直观的。 当A和B最初通过S交换地址信息时,他们应该包含自身的IP地址和端口号(从自己看),同时也包含从服务器看的自己的 地址和端口号。 然后客户端同时开始从对方已知的两个的地址中同时开始互相发送数据,并使用第一个成功通信的地址作为对方地址。如果两个客户端在同一个 NAT后,发送到对方内网地址的数据最有可能先到达。从而可以建立一条不经过NAT的通信链路;如果两个客户端在不同的NAT之后,发送给对方内网地址的数据包 根本就到达不了对方,但仍然可以通过公网地址来建立通路。

        总结就是,用户A给会用户B两组地址(A内网地址、通过S获取A的外网地址),同理B也会给A两组地址(B内网地址、通过S获取B的外网地址),用户A和用户B会互相发送消息,看哪个地址可以和对方进行通信(最终结果是通信最快的那对地址)。这也是ICE的工作原理,ICE将在后面介绍。

        UDP打洞技术有一个主要的条件:只有当两个NAT都是Cone NAT(或者非NAT的防火墙)时才能工作。 因为其维持了一个给定的(内网IP、内网UDP)二元组 和(公网IP、公网UDP)二元组固定的端口绑定,只要该UDP端口还在使用中,就不会变化。如果像对称NAT一样,给每个新会话分配一个新的公网端口。就会导致UDP应用程序无法使用跟外部端点已经打通了的通信链路。由于Cone NAT是当今最广泛使用的,尽管有一小部分的对称NAT是不支持打洞的,UDP打洞技术也还是被广泛采纳应用。

        如果打洞失败,那用户A和用户B只能通过S转发消息,即中继。

        STUN/TURN协议就是对上述的打洞流程进行了规范化、流程化,其中S就是STUN/TURN服务器,STUN是打洞协议,TURN是中继协议,TURN也可以是单独的一个服务。如下表所示,为不同类型NAT打洞成功的条件:

C1的NAT类型C2的NAT类型能否穿越防火墙
完全锥型完全锥型
完全锥型受限锥型
完全锥型端口受限锥型
完全锥型对称型
受限锥型受限锥型
受限锥型端口受限锥型
受限锥型对称型
端口受限锥型端口受限锥型
端口受限锥型对称型无法打通
对称型对称型无法打通

        目前主要有下面两种方式去尝试穿越对称NAT:

        同时开放TCP(SimultaneousTCP open)策略:
        如果 Client A和 Client B能够彼此正确的预知对方的NAT将会给下一个TCP连接分配的公网TCP端口,并且两个客户端能够同时地发起一个面向对方的“外出”的TCP连接请求,并在对方的 SYN 包到达之前,自己刚发送出去的SYN包都能顺利的穿过自己的NAT的话,一条端对端的TCP连接就能成功地建立了。

        这种策略存在的问题: 时钟严格一致,很难做到。

        UDP端口猜测策略:
        通常,对称NAT分配端口有两种策略,一种是按顺序增加,一种是随机分配。如果这里对称NAT使用顺序增加策略,那么,ClientB将两次被分配的IP、端口二元组发送给Server后,Server就可以通知ClientA在这个端口范围内猜测刚才ClientB发送给它的socket中被NAT映射后的IP、端口二元组,ClientA很有可能在孔有效期内成功猜测到端口号,从而和ClientB成功通信。

        这种策略存在的问题:不能为随机分配端口的对称型NAT打洞。

二、ICE

        ICE(Interactive Connectivity Establishment)是一种用于 NAT(网络地址转换)穿越的框架,通常用于实时通信应用中,帮助两端设备或应用在 NAT 后建立连接。ICE 主要用于实现端到端的通信连接,尤其是在 P2P(Peer-to-Peer)协议中,通常与 STUN(Session Traversal Utilities for NAT)和 TURN(Traversal Using Relays around NAT)一起使用。

        ICE参考:交互式连接建立(ICE) - Rose - SDL中文论坛 - Powered by Discuz!

        具体介绍ICE框架之前先了解几个概念:

        Offer/Answer模型:两端的地址交换是通过交换SDP实现的,主叫端把自己的SDP发送给被叫端的过程叫Offer,被叫端把自己的SDP发送给主叫端的过程叫Answer。Offer/Answer就是SDP交换过程,对应SIP中 INVITE请求(带有SDP)就是Offer,对端回复200 OK(带有SDP)就是Answer。

        candidate:候选地址,由IP、端口及协议(TCP、UDP,一般为UDP),简单来说candidate就是通信地址。candidate有四种类型:

类型别名如何传给对端用法
主机候选host信令服务器从网卡中获取的本地传输地址,如果此地址位于NAT之后,则为内网地址
服务器反射候选srflx信令服务器从发送给Stun服务器的Binding检查中获取的传输地址。如果此地址位于NAT之后,则为最外层NAT的公网地址
对端反射候选prflxStun Binding请求从对端发送的Stun Binding请求获取的传输地址。这是一种在连接检查期间新发生的候选项
中继候选relay信令服务器媒体中继服务器的传输地址。通过使用TURN Allocate请求获取

        地址对:就是一对ip:port,例如<ip1:port>-<ip2-port2>,表示p2p两端用户的地址。

        接下来看一下ICE的交互框架,如下图所示:

        交互式连接建立是一种标准穿透协议,利用Stun和Turn服务器来帮助端点建立连接,收集到的候选地址通过SDP在两端交换。

         ICE 的工作流程
        候选地址收集:在通信开始时,每个端点(客户端)都会生成自己的候选地址。候选地址包括主机地址、NAT的映射地址(通过 STUN 服务器获取)、以及 中继地址(通过 TURN 服务器获取,用于无法P2P的时候进行媒体数据转发)。
        候选地址交换:通过信令协议(如 SIP、WebRTC 等),每个端点将其候选地址发送给对方,确保双方都能得到彼此的候选地址。
        连接性检查:双方使用 STUN 协议对所有候选地址进行连接性检查,以确定最适合的连接路径。
        选择最佳路径:ICE 会根据优先级选择最佳的连接候选,并最终建立P2P连接。

        如果加上信令服务器(SIP、WebRTC等,信令服务器实际就是转发信令消息的代理服务器),框架入下图所示:

       

        A、B收集并交换完地址之后,A和B都拿到如下地址:

别名类型
A$Cand1host192.168.1.105
A$Cand2srflx211.161.240.181(raddr: 192.168.1.105)
B$Cand1host192.168.0.204
B$Cand2srfix11.92.14.8(raddr: 192.168.0.204)

        接下来A、B的ICE代理都会产生如下候选地址对:

本地网卡地址对端地址状态
192.168.1.105:60001192.168.0.204:40001未进行过Stun检查
211.161.240.181:60003192.168.0.204:40001未进行过Stun检查
192.168.1.105:6000111.92.14.8:50002未进行过Stun检查
211.161.240.181:6000311.92.14.8:50002未进行过Stun检查

        表中有一条、或多条、或没有,能够把A的视频Rtp数据发向B的视频Rtp通道,到底怎么个可能性就要执行接下的Stun检查。A、B的ICE代理会设置上面地址对的优先级,ICE规定了优先级计算方法,A、B计算出来的优先级是一样的。 

        关于中继候选,中继服务器会给A、B都分配一个地址ip-a:port-a、ip-b:port-b。B向ip-a:port-a发送的数据会被转发到A,用户A发送ip-b:port-b的数据也会转发到B,如下图所示(B是公网环境,TURN Client就在ICE代理内包含的):

        STUN检查也就是地址对的连通性检测,Stun检查具体操作是向对端上发Stun Binding请求。由于要能支持STUN应答,每个ICE代理必须内置Stun服务器功能。联通性检测就是STUN的四次握手过程,如下图所示:

        注意:

        上面的过程可能产生(注意是可能,不是一定,要看NAT是什么类型的)一组新的映射地址(端口不一样),类型为prflx,这个地址将会被添加到A、B的候选地址对中参与连通性检测。

        还有一种可能,假如A和Stun服务器之间连接状态不好,在它收到B发来的srflx(11.92.14.8)之后还没得出自己的srflx(211.161.240.181)。虽然A没得到自己的srflx,但这不妨碍对B的srflx这个候选地址进行Stun检查,于是会向11.92.14.8发Stun请求。B收到这个请求,从请求解析出211.161.240.181。虽然这个地址在值上等于A的srflx,但不是从信令服务器得到,而是来自对端的Stun请求。此时B就会以这个prflx新建Connection(地址对)。A在之后终于向Stun服务器拿到了自己的srflx,并通过信令服务器发向B。B发现这个srflx地址对已存在,就不会再创建了。

        经过连通信检测过后A、B会选出一个合适的地址对,自此打洞完成,A、B开始P2P音视频通话。

        ICE交互过程还包括:A、B角色选择(谁负责发起STUN的四次握手请求)、地址对排序(优先级计算公式)、冻结候选、连通性检测的调度、认证机制、保活等。这些属于ICE的实现细节,这里不展开描述,不过好在有ICE开源库都实现了这些功能,我们直接用就是了。总计一下:ICE = STUN + TURN + 协商机制 +协商路径。

三、ICE中的SDP

        SDP中包含了用户的候选地址。示例如下:

v=0
o=- 4610227990434322888 2 IN IP4 192.168.1.100
s=-
c=IN IP4 192.168.1.100
t=0 0
m=audio 5004 RTP/AVP 0 8 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
m=video 5006 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=42e01f;packetization-mode=1a=ice-ufrag:username
a=ice-pwd:password
a=ice-options:tricklea=candidate:0 1 UDP 2122252543 192.168.1.100 5004 typ host
a=candidate:1 1 UDP 1686052607 10.0.0.1 5004 typ srflx raddr 192.168.1.100 rport 5004
a=candidate:2 1 UDP 3355443200 203.0.113.5 5004 typ relay raddr 192.168.1.100 rport 5004

        a=ice-ufrag:username-->ice-ufrag 是 ICE 用户标识符的一部分。它用于与 ice-pwd 共同构成身份验证机制。

        a=ice-pwd:password-->ice-pwd 是 ICE 密码的一部分。它与 ice-ufrag 一起用于验证连接的有效性和安全性。

        a=ice-options:trickle-->ice-options 表示支持的 ICE 选项。trickle 选项表示支持“逐步”候选地址的传输,即当候选地址被发现时,可以逐步发送它们,而不需要等待所有地址都发现后再发送。

         a=candidate:格式:

a=candidate:<foundation> <component> <transport> <priority> <connection-address> <port> typ <candidate-type> [raddr <rel-addr> rport <rel-port>] [generation <gen>] [network-id <id>] [network-cost <cost>]

        字段解释:
        foundation:每个候选地址的唯一标识符,用于标识候选地址的基础。通常是候选的一个哈希值。
        component:媒体流的组件类型,通常为 1(表示音频)或 2(表示视频)。
        transport:传输协议。常见的值有 UDP 和 TCP,这指定了候选地址所使用的协议。
        priority:候选地址的优先级,值越大优先级越高。优先级的计算基于 RFC 5245 中定义的算法,通常考虑了连接的可靠性和速度等因素。
        connection-address:候选地址的 IP 地址。可以是主机的私有地址、公共地址,或者 STUN/TURN 服务器返回的地址。
        port:与候选地址关联的端口号。
        typ:候选地址的类型。常见的类型有:
                host:本地地址。
                srflx(server reflexive):通过 STUN 服务器映射得到的地址。
                relay:通过 TURN 服务器中继得到的地址。
        raddr:(可选)在使用 srflx 或 relay 类型时,表示用于映射的远程地址(STUN/TURN 服务器的地址)。
        rport:(可选)在使用 srflx 或 relay 类型时,表示用于映射的远程端口。
        generation:(可选)候选的生成编号,用于多次候选的情况。通常为 1 或 2。
        network-id:(可选)网络标识符,用于区分不同网络接口上的候选地址。
        network-cost:(可选)网络代价,用于衡量候选地址的质量,数值越小代表代价越低,通常是基于带宽或延迟的评估。

        关于STUN/TURN协议不过多介绍,这里只是介绍整体框架,对于基于SIP的VOIP通话,PJSIP已经实现了ICE框架,可直接使用。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

python桌面工具

用处 使用该工具可以将excel内容转成SQL语句&#xff0c;可以使用到一些SQL的报表平台可以将json文件转成xlsx格式文件 前期准备 安装库 pip install pandas -i https://mirrors.aliyun.com/pypi/simplepip install wxpython -i https://mirrors.aliyun.com/pypi/simplepip i…

【Golang】Go语言编程思想(一):接口

接口 接口的概念 现在我们要实现一个函数&#xff0c;用于对给定的 url 进行解析&#xff0c;具体的代码实现如下&#xff1a; package mainimport ("fmt""io""net/http" )func retrieve(url string) string {resp, err : http.Get(url)if er…

SAP SD 如何设置交货单数量可修改为0

在日常运维中&#xff0c;销售订单可以被reject&#xff0c;但是交货单只能被物理删除 但是粗暴的物理删除&#xff0c;又会使得单据不连续&#xff0c;出现问题不好追溯 所以我们就可以通过将废弃的交货单的数量置为0 配置如下&#xff1a; C表示&#xff0c;创建的时候不可…

记一次由docker容器使得服务器cpu占满密码和密钥无法访问bug

Bug场景&#xff1a; 前几天在服务器上部署了一个免费影视网站&#xff0c;这个应用需要四个容器&#xff0c;同时之前的建站软件workpress也是使用docker部署的&#xff0c;也使用了三个容器。在使用workpress之前&#xff0c;我将影视软件的容器全部停止。 再使用workpress…

Matlab R2024b 中文版 下载及安装教程

点击下方链接下载安装包 Matlab R2024b 中文版安装包点击下载https://mp.weixin.qq.com/s/Kq2j1dQLdULOVV9vrA6pkA 安装教程 1.通过上方链接下载软件&#xff0c;鼠标右键【MATLAB R2024b(64bit)】压缩包&#xff0c;选择解压到MATLAB R2024b(64bit)。 2.双击进入解压后的文…

2024年12月6日Github流行趋势

项目名称&#xff1a;lobe-chat 项目维护者&#xff1a;arvinxx, semantic-release-bot, canisminor1990, lobehubbot, renovate项目介绍&#xff1a;一个开源的现代化设计的人工智能聊天框架。支持多AI供应商&#xff08;OpenAI / Claude 3 / Gemini / Ollama / Qwen / DeepSe…

韩企研学团造访图为科技:共探人工智能创新前沿

今日&#xff0c;一支由韩国知名企业研学专家组成的代表团莅临图为科技深圳总部&#xff0c;展开了一场深度技术交流与研讨活动。 此次访问旨在通过实地探访中国领先的科技企业&#xff0c;促进中韩两国在科技创新领域的深入合作与交流。 韩国游学团合影 图为科技作为一家在人…

Vulnhub---kioptirx4 udf手工提权

个人博客 WuTongSec 打点 nmap -sP 192.168.128.0/24 找机器 nmap -P- 192.168.128.135 端口快扫 nmap -min-rate 10000 -sV -sC -O 192.168.128.135 脚本并没有扫出 什么洞 dirsearch -u http://192.168.128.135 目录扫描 三个200 那就先上web看看 web是应该登录框 在pas…

基于RISC-V的HSM方案

安全之安全(security)博客目录导读 本篇博客&#xff0c;我们聚焦RISC-V 2024中国峰会上RISC-V的一个HSM&#xff08;Hardware Security Module&#xff09;实现方案&#xff0c;来自芯来科技王松老师。 关于RISC-V TEE(可信执行环境)的相关方案&#xff0c;如感兴趣可参考RIS…

【C++探索学习】第十九弹——进程替换:深入解析操作系统中的进程替换机制

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 在Linux操作系统中&#xff0c;进程替换&#xff08;Process Replacement&#xff09;是一个重要的概念&#xff0c;它允许程序通过系统调…

[软件工程]八.软件演化

8.1什么是软件演化 由于种种不可避免的原因&#xff0c;系统开发完成后的软件需要进行修改来适应变更的需求&#xff0c;我们对软件的修改就叫软件演化。 8.2为什么软件会演化 由于业务的变更或者为了满足用户期待的改变&#xff0c;使得对已有的系统的新需求浮现出来。由于…

WiFi受限不再愁,电脑无网络快速修复指南

有时在试图连接WiFi时&#xff0c;会发现网络连接受限&#xff0c;或无法正常访问互联网。这种情况不仅影响了工作效率&#xff0c;还可能错过重要的信息。那么&#xff0c;究竟是什么原因导致了电脑WiFi连接受限呢&#xff1f;又该如何解决这一问题呢&#xff1f;小A今天就来教…

【Liunx篇】基础开发工具 - yum

文章目录 &#x1f335;一.Liunx下安装软件的方案&#x1f43e;1.源代码安装&#x1f43e;2.rpm包安装&#x1f43e;3.包管理器进行安装 &#x1f335;二.软件包管理器-yum&#x1f335;三.yum的具体操作&#x1f43e;1.查看软件包&#x1f43e;2.安装软件包&#x1f43e;3.卸载…

第七节(2)、T型加减速优化处理【51单片机-TB6600驱动器-步进电机教程】

摘要&#xff1a;本节介绍解决标准T型加减速过程中的两个缺陷&#xff0c;其一是使得初速度任意设置&#xff1b;其二是降低Cn递推计算量&#xff0c;提升速度上限 一. 加速减速过程计算 1.1计算不存在匀速过程 根据基本运动定理&#xff1a; w m a x w 0 a 0 ∗ t n 0 … …

什么是继承性?C++中如何实现继承? 继承的好处和注意事项有哪些?

1) 什么是继承性&#xff1f;C中如何实现继承&#xff1f; 一、继承性的概念 继承性是面向对象编程中的一个重要特性&#xff0c;它允许一个类&#xff08;称为子类或派生类&#xff09;继承另一个类&#xff08;称为父类或基类&#xff09;的属性和方法。继承的主要目的是实现…

唇形同步视频生成工具:Wav2Lip

一、模型介绍 今天介绍一个唇形同步的工具-Wav2Lip&#xff1b;Wav2Lip是一种用于生成唇形同步&#xff08;lip-sync&#xff09;视频的深度学习算法&#xff0c;它能够根据输入的音频流自动为给定的人脸视频添加准确的口型动作。 &#xff08;Paper&#xff09; Wav2Lip模型…

ESP32使用TCA9548A IIC多路复用器拓展

ESP32使用TCA9548A IIC多路复用器拓展 本文将讲述如何使用TCA9458A IIC多路复用器扩展IIC总线端口。使用相同的IIC地址控制多个IIC设备&#xff0c;如多个OLED或BME280等 TCA9548介绍 IIC通信协可以实现在同一IIC总线上与多个IIC设备通信&#xff0c;只要所有设备都具有唯一…

BGP路径属性与路由反射器

BGP路径属性 路径属性&#xff1a; 任何一条BGP路由都拥有多个路径属性 当路由器将BGP路由通告给它的对等体时&#xff0c;一并被通告的还有路由所携带的各各路径属性 BGP的路径属性将影响路由优选 路径四个属性分类&#xff1a; 公认必遵&#xff1a;必须包括在每个upda…

C语言期末考试——重点考点

目录 1.C语言的结构 2.三种循环结构 3.逻辑真假判断 4. printf函数 5. 强制类型转化 6. 多分支选择结构 7. 标识符的定义 8. 三目运算符 1.C语言的结构 选择结构、顺序结构、循环结构 2.三种循环结构 for、while、do-while 3.逻辑真假判断 C语言用0表示false,用非0(不…

ci/cd配置任务超时时间

有两个地方决定了任务超时时间&#xff1a; 1. 2.gitlab-runner