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

news2025/5/21 18:58:17

        我的音视频/流媒体开源项目(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=1

a=ice-ufrag:username
a=ice-pwd:password
a=ice-options:trickle

a=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.coloradmin.cn/o/2256958.html

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

相关文章

Spring Boot如何实现防盗链

一、什么是盗链 盗链是个什么操作&#xff0c;看一下百度给出的解释&#xff1a;盗链是指服务提供商自己不提供服务的内容&#xff0c;通过技术手段绕过其它有利益的最终用户界面&#xff08;如广告&#xff09;&#xff0c;直接在自己的网站上向最终用户提供其它服务提供商的…

5.内容管理模块-课程查询

搞清楚一个项目的业务流程最直接的手段&#xff0c;就是找一个账号登录进去&#xff0c;操作一遍。 3.3设计接口 接口设计分析 post在需要提交很多参数的时候使用&#xff0c;并且post的安全性较高。 接口分析&#xff1a; po包&#xff0c;一般存放和数据库交互的实体类。 …

网络编程 | TCP套接字通信及编程实现经验教程

1、TCP基础铺垫 TCP/IP协议簇中包含了如TCP、UDP、IP、ICMP、ARP、HTTP等通信协议。TCP协议是TCP/IP协议簇中最为常见且重要的通信方式之一&#xff0c;它为互联网上的数据传输提供了可靠性和连接管理。 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议…

vue3组件间传值

definProps方式 子组件&#xff1a;assignSuppliers.vue const propdefineProps({fid:String}); 父组件&#xff1a;index.vue <!-- 供应商分配 --><n-drawerwidth"800"v-model:visible"drawerSupplierConfig.visible":title"drawerSuppli…

《网络安全编程基础》之Socket编程

我的代码 server.c // server.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <Winsock2.h> #pragma comment(lib,"ws2_32.lib") //添加静态链接库文件 void main(int argc,char* argv[]) {WSADATA …

不只是请求和响应:使用Fiddler解读Cookie与状态码全指南(下)

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持! 不只是请求和响应&#xff1a;使用Fiddler抓包HTTP协议全指南(上)_fiddler 获取响应脚本-CSDN博客https://blog.csdn.net/Chunfeng6yugan/article/details/144005872?spm1001.2014.3001.5501 不只是请求和响…

Linx下自动化之路:Redis安装包一键安装脚本实现无网极速部署并注册成服务

目录 简介 安装包下载 安装脚本 服务常用命令 简介 通过一键安装脚本实现 Redis 安装包的无网极速部署&#xff0c;并将其成功注册为系统服务&#xff0c;开机自启。 安装包下载 redis-7.0.8.tar.gzhttp://download.redis.io/releases/redis-7.0.8.tar.gz 安装脚本 修…

第3章.垃圾收集器与内存分配策略

概述 对象已死 引用计数法 可达性分析算法 再谈引用 生存还是死亡 回收方法区 垃圾收集算法 分代收集理论 3种垃圾收集算法 HotSpot的算法细节实现 根节点枚举 安全点 安全区域 记忆集与卡表 写屏障 并发的可达性分析 误消亡问题 经典垃圾收集器 概述 简单的一些GC CMS G1 低延…

Python 类的设计(以植物大战僵尸为例)

关于类的设计——以植物大战僵尸为例 一、设计类需满足的三要素1. 类名2. 属性和方法 二、以植物大战僵尸的为例的类的设计1. 尝试分类2. 创建对象调用类的属性和方法*【代码二】*3. 僵尸的继承 三、代码实现 一、设计类需满足的三要素 1. 类名 类名&#xff1a;某类事物的名…

如何使用WinCC DataMonitor基于Web发布浏览Excel报表文档

本文介绍使用 WinCC DataMonitor 的 "Excel Workbooks" 功能&#xff0c;通过 Excel 表格显示 WinCC 项目的过程值、归档变量值和报警归档消息。并可以通过 Web 发布浏览访问数据 1&#xff0e;WinCC DataMonitor是什么 ? DataMonitor 是 SIMATIC WinCC 工厂智能中…

【Java】—— 图书管理系统

基于往期学习的类和对象、继承、多态、抽象类和接口来完成一个控制台版本的 “图书管理系统” 在控制台界面中实现用户与程序交互 任务目标&#xff1a; 1、系统中能够表示多本图书的信息 2、提供两种用户&#xff08;普通用户&#xff0c;管理员&#xff09; 3、普通用户…

记录ubuntu22.04重启以后无法获取IP地址的问题处理方案

现象描述&#xff1a;我的虚拟机网络设置为桥接模式&#xff0c;输入ifconfig只显示127.0.0.1&#xff0c;不能连上外网。&#xff0c;且无法上网&#xff0c;用ifconfig只有如下显示&#xff1a; 1、sudo -i切换为root用户 2、输入dhclient -v 再输入ifconfig就可以看到多了…

异步操作,promise、axios

一、异步操作&#xff08;异步编程&#xff09;、同步操作 异步操作是指在编程中&#xff0c;某个任务的执行不会立即完成&#xff0c;同时不会阻塞后续代码的执行。在异步操作中&#xff0c;程序可以继续运行&#xff0c;并在异步任务完成时得到通知并处理结果。这与同步操作…

第一性原理构造医疗信创域高质量发展路径应用探析

门诊电子病历录入 摘要&#xff1a; 主要介绍了第一性原理在医疗系统开发中的应用及其重要性。阐述了第一性原理的概念及发展历程&#xff0c;并指出其在各个领域的重要性和应用价值。详细分析了第一性原理在医疗系统开发中的具体影响&#xff0c;包括对医院管理和互联网医疗的…

MySQL8下载安装教程

前言 1.个人经验&#xff0c;仅供参考&#xff01;&#xff01;&#xff01; 2.如果之前有下载过MySQL&#xff0c;请检查是否有删除干净&#xff0c;在控制面板删除最好 下载网址&#xff1a;MySQL :: MySQL Community Downloads 下载步骤 进入网址选择要下载的 下一步网…

算法日记 45 day 图论(并查集基础)

并查集解决什么问题 并查集常用来解决连通性问题。 大白话就是当我们需要判断两个元素是否在同一个集合里的时候&#xff0c;我们就要想到用并查集。 原理 既然是查找是否在同一个集合中&#xff0c;那么这个集合是怎么构建的呢&#xff1f;用一维数组来表示一个有向图&…

PTA DS 6-4 带头结点的链队列的基本操作 (C补全函数)

6-4 带头结点的链队列的基本操作 分数 10 全屏浏览 切换布局 作者 黄复贤 单位 菏泽学院 实现链队列的入队列及出队列操作。 函数接口定义&#xff1a; Status QueueInsert(LinkQueue *Q,ElemType e)&#xff1b; Status QueueDelete(LinkQueue *Q,ElemType *e)&#x…

Windows 系统没有网络链接常见原因以及解决方案

在使用 Windows 电脑时&#xff0c;有时会遇到电脑显示已连接网络&#xff0c;但却无法访问 Internet 的情况&#xff0c;这可能是由多种原因导致的。以下简鹿办公将详细介绍一些常见原因及对应的解决方案。 一、网络连接问题 原因 路由器故障&#xff1a;路由器长时间运行可…

lnmp+discuz论坛 附实验:搭建discuz论坛

Inmpdiscuz论坛 Inmp: t: linux操作系统 nr: nginx前端页面 me: mysql数据库 账号密码&#xff0c;等等都是保存在这个数据库里面 p: php——nginx擅长处理的是静态页面&#xff0c;页面登录账户&#xff0c;需要请求到数据库&#xff0c;通过php把动态请求转发到数据库 n…

杨振宁大学物理视频中黄色的字,c#写程序去掉

先看一下效果&#xff1a;&#xff08;还有改进的余地&#xff09; 我的方法是笨方法&#xff0c;也比较刻板。 1&#xff0c;首先想到&#xff0c;把屏幕打印下来。c#提供了这样一个函数&#xff1a; Bitmap bmp new Bitmap(640, 480, PixelFormat.Format32bppArgb); // 创…