【开发指南】HTML和JS编写多用户VR应用程序的框架

1.概述

Networked-Aframe 的工作原理是将实体及其组件同步到连接的用户。要连接到房间,您需要将networked-scene组件添加到a-scene元素。对于要同步的实体,请向其添加networked组件。默认情况下,positionrotation组件是同步的,但如果您想同步其他组件或子组件,则需要定义架构。有关网络消息的更高级控制,请参阅广播自定义消息和选项部分。

2.场景组件

A-Frame<a-scene>上的组件。

<a-scene networked-scene="serverURL: /;app: <appId>;room: <roomName>;connectOnLoad: true;onConnect: onConnect;adapter: wseasyrtc;audio: false;video: false;debug: false;
">...
</a-scene>

属性

描述

默认值

serverURL

选择 WebSocket/信令服务器所在的位置。

/

app

唯一的应用程序名称。不允许有空格。

default

room

独特的房间名称。每个应用程序可以有多个。不允许有空格。每个应用程序可以有多个房间,客户端只能连接到同一应用程序和房间中的客户端。

default

connectOnLoad

网页加载后立即连接到服务器。

true

onConnect

当客户端成功连接到服务器时调用的函数。

onConnect

adapter

您要使用的网络服务,请参阅适配器。

wseasyrtc

audio

打开/关闭您的应用程序的麦克风音频流。仅当所选适配器支持时才有效。

false

video

打开/关闭您的应用程序的视频流。仅当所选适配器支持时才有效。

false

debug

打开/关闭 Networked-Aframe 调试日志。

false

3.连接

默认情况下,networked-scene将自动连接到您的服务器。为了防止这种情况发生并控制何时连接,请在networked-scene中将connectOnLoad设置为 false。当您准备好连接时,会在a-scene元素上发出connect事件。

AFRAME.scenes[0].emit('connect');

4.断开连接

要断开连接,只需从a-scene元素中删除networked-scene组件即可。

AFRAME.scenes[0].removeAttribute('networked-scene');

从页面中完全删除a-scene也可以彻底断开连接。

5.创建网络实体

<a-assets><template id="my-template"><a-entity><a-sphere color="#f00"></a-sphere></a-entity></template>
</a-assets><!-- Attach local template by default -->
<a-entity networked="template: #my-template">
</a-entity><!-- Do not attach local template -->
<a-entity networked="template:#my-template;attachTemplateToLocal:false">
</a-entity>

创建要在客户端之间同步的模板实例。默认情况下,位置和旋转将同步。buffered-interpolation库用于允许更少的网络更新,同时保持平滑的运动。

模板只能有一个根元素。当attachTemplateToLocal设置为true时,该元素上的属性将被复制到本地实体,并且子元素将被附加到本地实体。远程实例化的实体将是模板根元素的副本,并添加了networked组件。

(1)attachTemplateToLocal=true示例

<a-entity wasd-controls networked="template:#my-template">
</a-entity><!-- Locally instantiated as: -->
<a-entity wasd-controls networked="template:#my-template"><a-sphere color="#f00"></a-sphere>
</a-entity><!-- Remotely instantiated as: -->
<a-entity networked="template:#my-template;networkId:123;"><a-sphere color="#f00"></a-sphere>
</a-entity>

(2)attachTemplateToLocal=false示例

<a-entity wasd-controls networked="template:#my-template;attachTemplateToLocal:false;">
</a-entity><!-- No changes to local entity on instantiation --><!-- Remotely instantiated as: -->
<a-entity networked="template:#my-template;networkId:123;"><a-sphere color="#f00"></a-sphere>
</a-entity>
 

属性

描述

默认值

template

存储在<a-assets>中的模板标签的 css 选择器

''”

attachTemplateToLocal

设置为 false 时,不附加本地用户的模板。当本地和远程存在不同行为时,这非常有用。

true

persistent

在远程创建者(而非所有者)断开连接时,尝试获取持久实体的所有权而不是删除它们

false

6.删除网络实体

目前只有网络实体的创建者可以删除它。要删除,只需使用常规 DOM API 从 HTML 中删除元素,Networked-Aframe 将自动处理同步。

7.同步自定义组件

默认情况下,根实体上的positionrotation组件是同步的。

要同步其他组件和子实体的组件,您需要为每个模板定义一个架构。以下是定义和添加架构的方法:

NAF.schemas.add({template: '#avatar-template',components: ['position','rotation','scale',{selector: '.hairs',component: 'show-child'},{selector: '.head',component: 'material',property: 'color'},]
});

根实体的组件可以用组件的名称来定义。子实体的组件可以使用具有selector字段和component字段的对象来定义,该字段使用document.querySelector使用的标准 CSS 选择器它指定组件的名称。要仅同步多属性组件的一个属性,请添加带有属性名称的property字段。

定义架构后,通过调用NAF.schemas.add(YOUR_SCHEMA)将其添加到架构列表中。

组件数据由 A-Frame 组件data属性检索。在网络更新期间,每个组件的数据都会根据其之前的同步值进行检查;如果数据对象发生了任何变化,它将通过网络同步。

8.同步组件优化

对于每个组件,您可以定义一个requiresNetworkUpdate函数,该函数采用当前值,如果当前值较之前值发生更改,则返回 true。如果当前值和先前值足够接近,您可以返回 false,以免将此更改发送给其他参与者。

默认情况下,当您未定义它时,它始终使用defaultRequiresUpdate函数(在networked.js顶部定义),该函数使用通用deepEqual函数来将当前值与前一个值进行比较,当两个值不同时使用cachedData = AFRAME.utils.clone(newData);以保留前一个值以供下次比较。AFRAME.utils.clone实现正做JSON.parse(JSON.stringify(obj)),可以与任何类型一起使用,但这可能不是 Vector3 类型(如位置、旋转、缩放)的最佳性能实现。

只是为了让你知道这是在做什么:

> const v = new THREE.Vector3(1,2,3);
Vector3 {x: 1, y: 2, z: 3}
> JSON.parse(JSON.stringify(v))
{x: 1, y: 2, z: 3}

因此,如果值发生变化,每次同步过程完成时都会在内存中创建一个新对象,这些对象会在某一时刻被垃圾收集。如果场景很重,垃圾收集通常可能需要 1 毫秒或更长的时间,结果可能是浏览器丢掉一些帧,因此没有一致的 fps。您可以使用 Chrome 分析器来确认这一点。对于移动的头像来说,这一点几乎不会被注意到,但如果用户拥有大量连续移动的对象,这对于您的用例可能很重要。

此外,使用当前的 aframewasd-controls实现以及位置平滑方式,在用户停止按键后 2 秒,玩家位置的变化仍然低于毫米精度,因此通过网络发送大量 NAF 消息视觉上不易察觉的位置变化。 NAF 已经包含位置插值来平滑接收到的位置变化,因此通过网络发送所有这些位置变化甚至是多余的。

您可以使用专用函数来比较给定精度的两个 Vector3,通过避免创建新对象,通过网络和内存发送更少的消息来实现更好的性能:

const vectorRequiresUpdate = epsilon => {return () => {let prev = null;return curr => {if (prev === null) {prev = new THREE.Vector3(curr.x, curr.y, curr.z);return true;} else if (!NAF.utils.almostEqualVec3(prev, curr, epsilon)) {prev.copy(curr);return true;}return false;};};
};

这个函数实际上是在NAF.utils.vectorRequiresUpdate中定义的,供你使用。

要在网络模式中使用它以获得 1 毫米的位置精度和 0.5 度的旋转精度,请按如下方式使用:

{template: '#avatar-template',components: [{component: 'position',requiresNetworkUpdate: NAF.utils.vectorRequiresUpdate(0.001)},{component: 'rotation',requiresNetworkUpdate: NAF.utils.vectorRequiresUpdate(0.5)}]
}

从0.11.0版本开始,同步位置和旋转的默认模式使用上述优化。

9.同步嵌套模板 - 例如:手

要同步嵌套模板,请像这样设置 HTML 节点:

<a-entity id="player" networked="template:#player-template;attachTemplateToLocal:false;" wasd-controls><a-entity camera look-controls networked="template:#head-template;attachTemplateToLocal:false;"></a-entity><a-entity hand-controls="hand:left" networked="template:#left-hand-template"></a-entity><a-entity hand-controls="hand:right" networked="template:#right-hand-template"></a-entity>
</a-entity>

在此示例中,头部/摄像头、控制器的左手和右手将生成自己的模板,这些模板将独立于根玩家进行联网。注意:这与当前不支持的手部追踪无关。这种父子关系仅在一个级别之间有效,即。子实体的直接父实体必须具有networked组件。

您需要自己定义左手和右手模板,以便向其他用户显示手部模型。只有位置和旋转会同步给其他用户。要同步手势,请参阅下面的networked-hand-controls组件。

10.带同步手势的跟踪控制器

这是比上述更简单的替代方案。 NAF 允许轻松添加其他人可见的手部模型,这些模型显示与触摸的按钮相匹配的模拟手势(不是手部跟踪),这样您就可以向房间里的其他人指向并竖起大拇指或握拳。

您所要做的就是使用内置的networked-hand-controls组件,将这两个实体添加为相机装备的子级:

<a-entityid="my-tracked-left-hand"networked-hand-controls="hand:left"networked="template:#left-hand-default-template"
></a-entity>
<a-entityid="my-tracked-right-hand"networked-hand-controls="hand:right"networked="template:#right-hand-default-template"
></a-entity

您可以设置的公共架构属性有:

属性

描述

默认值

取值范围

color

将被设置为材质颜色

white

hand

指定实体是用于左手还是右手

left

left, right

handModelStyle

A-Frame中可用的内置模型

highPoly

highPoly, lowPoly, toon, controller

customHandModelURL

可选的自定义手模型网址

请注意“控制器”选项——它将使用控制器本身的模型,根据您的平台自动正确设置——它还将广播模型支持的按钮网格更新。 (不幸的是,Quest 2 模型按钮网格目前存在一个错误,因此不会显示任何更新。)

networked-hand-controls正在完全替换hand-controls,不要同时使用两者。如果您使用如上所述的网络组件,则无需为每只手定义模板和网络架构。默认模板和网络模式已定义如下:

<template id="left-hand-default-template"><a-entity networked-hand-controls="hand:left"></a-entity>
</template>
<template id="right-hand-default-template"><a-entity networked-hand-controls="hand:right"></a-entity>
</template>
NAF.schemas.add({template: '#left-hand-default-template',components: [{component: 'position',requiresNetworkUpdate: NAF.utils.vectorRequiresUpdate(0.001)},{component: 'rotation',requiresNetworkUpdate: NAF.utils.vectorRequiresUpdate(0.5)},'networked-hand-controls']
});
NAF.schemas.add({template: '#right-hand-default-template',components: [{component: 'position',requiresNetworkUpdate: NAF.utils.vectorRequiresUpdate(0.001)},{component: 'rotation',requiresNetworkUpdate: NAF.utils.vectorRequiresUpdate(0.5)},'networked-hand-controls']
});

11.发送自定义消息

NAF.connection.subscribeToDataChannel(dataType, callback)
NAF.connection.unsubscribeToDataChannel(dataType)NAF.connection.broadcastData(dataType, data)
NAF.connection.broadcastDataGuaranteed(dataType, data)NAF.connection.sendData(clientId, dataType, data)
NAF.connection.sendDataGuaranteed(clientId, dataType, data)

订阅和取消订阅dataType指定的网络消息的回调。使用broadcastData功能向房间内的所有客户端广播数据。要仅发送到特定客户端,请改用sendData函数。

参数

描述

clientId

将此数据发送到的 ClientId

dataType

用于标识网络消息的字符串。u(更新)、um(UpdateMulti)和r(删除)是保留数据类型,请不要使用它们

callback

收到类型dataType的消息时调用的函数。参数:function(senderId, dataType, data, targetObj)使用 easyrtc 适配器,targetObj在广播消息时可以是{targetRoom: 'roomId'},或者在向特定参与者发送消息时可以是{targetEasyrtcid: 'targetId'}。对于 janus 适配器,senderId 始终为 null,并且targetObj更多的是source参数,通常等于“janus-event”。

data

要发送给所有其他客户端的对象

12.转让实体所有权

实体的所有者负责同步其组件数据。当用户想要修改另一个用户的实体时,他们必须首先获得该实体的所有权。所有权转移示例和切换所有权组件展示了如何获取实体的所有权并更新它。

NAF.utils.takeOwnership(entityEl)

取得实体的所有权。

NAF.utils.isMine(entityEl)

检查您是否拥有指定实体。

13.事件

当 NAF 中发生某些事情时,事件就会被触发。要订阅这些事件,请遵循以下模式:

document.body.addEventListener('clientConnected', function (evt) {console.error('clientConnected event. clientId =', evt.detail.clientId);
});

创建document.body元素后需要订阅事件。这可以通过等待document.bodyonLoad方法或使用 NAF 的onConnect函数来实现。使用 NAF 活动演示作为示例。

事件列表:

事件

描述

取值范围

clientConnected

当另一个客户端连接到您时触发

evt.detail.clientId- 连接客户端的ClientId

clientDisconnected

当另一个客户端与您断开连接时触发

evt.detail.clientId- 断开连接的客户端的ClientId

entityCreated

创建网络实体时触发

evt.detail.el- 新实体

entityRemoved

删除网络实体时触发

evt.detail.networkId- 已删除实体的网络ID

以下事件在networked组件上触发。有关示例,请参阅切换所有权组件。

所有权转让事件列表:

事件

描述

参数范围

ownership-gained

当网络实体的所有权被夺取时触发

evt.detail.el- 获得所有权的实体

evt.detail.oldOwner- 前任所有者的 clientId

ownership-lost

当网络实体的所有权丢失时触发

evt.detail.el- 失去所有权的实体

evt.detail.newOwner- 新所有者的 clientId

ownership-changed

当网络实体的所有权更改时触发

evt.detail.el- 失去所有权的实体

evt.detail.oldOwner- 前任所有者的 clientId

evt.detail.newOwner- 新所有者的 clientId

14.适配器

NAF 可与多个网络库和服务一起使用。适配器是一个向 NAF 添加对库的支持的类。如果您只是在开发一个小项目或概念验证,那么您可能会使用默认配置,并且可以跳过本节。评估不同适配器时应考虑的因素包括:

  • 一间房间需要支持多少个并发用户?

  • 您想托管自己的服务器吗?或者像 Firebase 这样的“无服务器”解决方案可以完成这项工作吗?

  • 您需要音频(麦克风)流吗?

  • 您需要自定义服务器端逻辑吗?

  • 您想要 WebSocket(客户端-服务器)网络架构还是 WebRTC(点对点)网络架构?

默认情况下使用wseasyrtc适配器,它不支持音频并使用 TCP 连接。这对于生产部署来说并不理想,但是由于 WebRTC 固有的连接问题,我们将其设置为默认值。要通过 WebRTC 支持音频,请确保服务器使用 https 并将适配器更改为easyrtc(这使用 UDP)。

支持的适配器列表:

适配器

描述

音频/视频支持情况

基于WebSocket 或 WebRTC

如何启动

wseasyrtc

默认 - 使用 open-easyrtc 库

No

WebSocket

npm run dev

easyrtc

使用 open-easyrtc 库

音频和视频(相机和屏幕共享)

WebRTC

npm run dev

janus

使用 Janus WebRTC 服务器和 janus-plugin-sfu

音频和视频(相机或屏幕共享)

WebRTC

参阅 naf-janus-adapter

socketio

无需外部库的 SocketIO 实现(服务器支持房间实例化)

No

WebSocket

npm run dev-socketio

webrtc

无需外部库的原生 WebRTC 实现(正在进行中,目前没有维护者)

音频

WebRTC

npm run dev-socketio

Firebase

用于 WebRTC 信号传输的 Firebase(目前没有维护者)

No

WebRTC

参阅 naf-firebase-adapter

uWS

uWebSockets 的实现(目前没有维护者)

No

WebSocket

参阅 naf-uws-adapter

表中的 WebRTC 表示组件更新使用 WebRTC 数据通道 (UDP),而不是 WebSocket (TCP)。您仍然有一个用于信令部分的 WebSocket。

更为详细比较,请参阅文档 NAF 适配器比较。

15.音频

audio: true添加到networked-scene组件(并使用支持它的适配器)后,默认情况下您将听不到任何音频。尽管音频将进行流式传输,但在创建具有networked-audio-source的实体之前,它是听不到的。来自该实体所有者的音频将从该实体的位置在 3D 空间中发出。networked-audio-source组件必须与networked组件一起添加到实体(或实体的子实体)。

要使麦克风静音/取消静音,您可以使用以下 API(easyrtc 和 janus 适配器):

NAF.connection.adapter.enableMicrophone(enabled)

其中enabledtruefalse

16.视频

video: true(janus 适配器不需要)添加到networked-scene组件(并使用支持它的适配器)后,默认情况下您将看不到任何视频。尽管视频将进行流式传输,但在创建使用带有networked-video-source的网格(例如<a-plane>)的实体之前,它是不可见的。来自该实体所有者的视频将在 3D 空间中从该实体的位置可见。networked-video-source组件必须添加到具有networked组件的实体的<a-plane>子实体中。

目前,这仅适用于支持getMediaStream(clientId, type="video")API 的 easyrtc 和 janus 适配器。

请参阅,该示例显示了没有音频的用户摄像头。

要禁用/重新启用相机,您可以使用以下 API(仅限 easyrtc 适配器):

NAF.connection.adapter.enableCamera(enabled)

其中enabledtruefalse

使用 easyrtc 适配器,您可以使用addLocalMediaStreamremoveLocalMediaStreamAPI 添加额外的视频轨道,例如屏幕共享:

navigator.mediaDevices.getDisplayMedia().then((stream) => {NAF.connection.adapter.addLocalMediaStream(stream, "screen");
});NAF.connection.adapter.removeLocalMediaStream("screen");

请参阅多流示例,该示例使用带有networked-video-source="streamName: screen"的第二个平面向其他参与者显示屏幕共享。请务必查看此示例 html 文件末尾的注释以了解已知问题。

17.杂项

NAF.connection.isConnected()

如果已与信令服务器建立连接,则返回 true。

NAF.connection.getConnectedClients()

返回当前连接的客户端列表。

18.选项

NAF.options.updateRate

每秒调用网络组件sync函数的频率。对于大多数社交 VR 应用程序来说,10-20 是正常的。默认为15

NAF.options.useLerp

默认情况下,当创建实体时,buffered-interpolation库用于平滑位置、旋转和缩放网络更新。如果您不希望在创建时使用此功能,请将其设置为 false。

19.离线使用

NAF 已经包含 easyrtc,因此运行npm run dev将提供完全有效的解决方案,而无需访问外部服务器。不过,这些示例确实依赖于 AFrame 和其他未与 NAF 打包的依赖项。因此,必须首先使 AFrame 适应离线工作,然后对所有其他组件执行相同的操作。这基本上可以归结为下载所使用的脚本及其内容,例如 3D 模型、字体等资产。建议在网络控制台打开时加载页面并识别哪些请求来自主机外部。

对于 VR,您还需要 https,因为浏览器需要它才能实现沉浸式模式。server/easyrtc-server.js文件中提供了说明。也就是说,您必须生成密钥和证书,将它们添加到本地 CA,然后通过 NAF 提供的 Express 服务器加载它们。确保在server/easyrtc-server.js顶部正确配置,并按照说明通过https.createServer进一步向下启用 https 本身。一旦您连接到 VR 中的 NAF 服务器,浏览器仍然会抱怨证书未知。您可以单击高级并继续。

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

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

相关文章

LabVIEW电路产品功能自动检测系统

开发基于LabVIEW的电路产品功能自动检测系统。该系统通过整合先进的硬件和软件技术&#xff0c;实现了电路产品的自动化测试&#xff0c;显著提高了测试效率和准确性&#xff0c;对于提升电子产品的可靠性和工作效率具有重要意义。 项目背景 在电子制造业中&#xff0c;电路产…

2.javaWeb_请求和响应的处理(Request,Response)

2.请求和响应的处理 文章目录 2.请求和响应的处理一、动态资源和静态资源javax.servlet(包) 二、Servlet体系1.简介2.HttpServlet3.Servlet生命周期 三、Request对象1.ServletRequest1)ServletRequest主要功能有&#xff1a;2)ServletRequest类的常用方法: 2.HttpServletReques…

请你谈谈:spring bean的生命周期 - 阶段2:Bean实例化阶段

在Spring框架中&#xff0c;Bean的实例化是Bean生命周期中的一个重要阶段。这个过程包括两个关键的子阶段&#xff1a;Bean实例化前阶段和Bean实例化阶段本身。 BeanFactoryPostProcessor&#xff1a;BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点&#xff0…

LG 选择 Flutter 来增强其智能电视操作系统 webOS

可以这个话题会让大多数人困惑&#xff0c;2024 年了为什么还会冒出 webOS 这种老古董&#xff1f;然后 LG 为什么选择 webOS &#xff1f;现在为什么又选择 Flutter &#xff1f; 其实早在 Google I/O 发布 Flutter 3.22 版本的时候&#xff0c;就提到了 LG 选择 Flutter 来增…

智慧园区整体解决方案3PPT(41页)

智慧园区整体解决方案概述智慧园区整体解决方案旨在通过先进的科技手段打造一个智能化、网络化的园区环境。该方案涵盖了私有云部署、智能会议系统、智慧物管、视频监控中心、消防监控中心、绿色健康大数据平台、智慧一卡通系统、智慧停车系统、智能餐厅、安全监控系统等多个方…

Flutter 状态管理新境界:多Provider并行驱动UI

前言 在上一篇文章中&#xff0c;我们讨论了如何使用 Provider 在 Flutter 中进行状态管理。 本篇文章我们来讨论如何使用多个 Provider。 在 Flutter 中&#xff0c;使用 Provider 管理多个不同的状态时&#xff0c;你可以为每个状态创建一个单独的 ChangeNotifierProvider…

Android中OkHttp3中超时时间概述

目录 前言connectTimeoutreadTimeoutwriteTimeoutcallTimeoutpingInterval拓展 前言 可以看到&#xff0c;使用还是很简单的。主要相关的有这五个参数&#xff0c;其中我们常用到是就是connectTimeout、readTimeout和writeTimeout。 再看上图&#xff0c;可以看到默认下connec…

电脑压缩视频文件 电脑压缩视频大小的方法

在数字化时代&#xff0c;视频已成为我们记录生活、分享快乐的重要工具。然而&#xff0c;大尺寸的视频文件常常让分享和存储变得棘手。如何在保持视频画质的前提下&#xff0c;轻松减小视频文件大小&#xff1f;今天&#xff0c;就让我们一起探索苹果电脑上的几种高效视频压缩…

探索Facebook的最新更新:社交体验的新高度

Facebook作为全球领先的社交媒体平台&#xff0c;一直致力于不断创新和改进&#xff0c;以提供更优质的用户体验。近期&#xff0c;Facebook推出了一系列新的更新&#xff0c;旨在提升用户的社交互动体验和平台功能。本文将详细探讨这些最新更新&#xff0c;分析其对用户和社交…

nginx全局块的user指令

文章目录 1、user指令1.1、进入nginx解压的目录1.2、./configure --help1.3、工作进程默认是nobody 2、user指令的使用步骤:2.1、设置一个用户信息"www"2.2、 创建一个用户2.3、./nginx -s reload2.4、创建/root/html/index.html页面&#xff0c;添加如下内容2.5、修…

数电基础 - 模数转换

目录 一. 简介 二. A/D转换器 三. 取样-保持电路 四. 并联比较型A/D转换器 五. 反馈比较型A/D转换器 六. 双积分型A/D转换器 七. V-F变换型A/D转换器 八. 总结 一. 简介 模数转换&#xff08;Analog-to-Digital Conversion&#xff0c;简称 ADC&#xff09;是将模拟信号…

AV1技术学习: Compound Prediction

一、双向 Compound Prediction AV1支持两个参考帧的预测通过多种复合模式线性组合。复合预测公式为 其中&#xff0c;权重m(x, y) is scaled by 64 以进行整数计算&#xff0c;R1(x, y)和R2(x, y)表示两个参考块中位于(x, y)的像素。P(x, y)将按比例缩小 1/64 以形成最终的预测…

taocms 3.0.1 本地文件泄露漏洞(CVE-2021-44983)

前言 CVE-2021-44983 是一个影响 taoCMS 3.0.1 的远程代码执行&#xff08;RCE&#xff09;漏洞。该漏洞允许攻击者通过上传恶意文件并在服务器上执行任意代码来利用这一安全缺陷。 漏洞描述 taoCMS 是一个内容管理系统&#xff08;CMS&#xff09;&#xff0c;用于创建和管…

使用 ABBYY FineReader PDF 15 在创建或转换 PDF 时自动生成书签

使用 ABBYY 为 PDF 文件添加书签&#xff0c;可以帮助快速定位文档中的主要内容&#xff0c;也能更方便的梳理出一份文档大纲。 有很多 PDF 文件在创建时并没有编辑书签&#xff0c;这里介绍使用 ABBYY FineReader PDF 15&#xff08;Win 系统&#xff09;在 PDF 中自动添加书…

Windows上LabVIEW编译生成可执行程序

LabVIEW项目浏览器(Project Explorer)中的"Build Specifications"就是用来配置项目发布方法的。在"Build Specifications"右键菜单中选取"New"&#xff0c;可以看到程序有几种不同的发布方法&#xff1a;Application(EXE)、Installer、.Net Inte…

EasyPhoto - 一键训练并生成人像写真,支持参考图生成 独立版 本地一键整合包下载

EasyPhoto最早是作为AI绘画软件StableDiffusion的一款插件备受大家喜爱&#xff0c;今天分享的是 EasyPhoto 的独立版本一键整合包&#xff0c;无需安装StableDiffusion即可解压即用。 和之前分享的腾讯开源的 PhotoMaker 和 阿里开源的 FaceChain 类似&#xff0c;EasyPhoto操…

数据库系统概论:数据库系统模式

数据库系统在我们的数字世界中扮演着至关重要的角色&#xff0c;无论是个人设备还是企业级应用&#xff0c;数据的有效管理和访问都是必不可少的。而数据库系统的模式结构是确保数据一致性和可访问性的关键组成部分。 数据库系统模式 基本概念 型和值 数据模型中有 型(type…

网络开局 与 Underlay网络自动化

由于出口和核心设备 部署在核心机房,地理位置集中,业务复杂,开局通常需要网络工程师进站调测。 因此核心层及核心以上的设备(包含核心层设备,旁挂独立AC设备和出口设备)推荐采用WEB网管开局方式或命令行开局方式。 核心以下的设备(包含汇聚层设备、接入层设备和AP)由于数量众…

MySQL第一次作业

一、库的建立 mysql> show databases; -------------------- | Database | -------------------- | information_schema | | mydb2_stuinfo | | mydb3_employee | | mydb4_product | | mydbl_test | | mysql | | performance…

【Java项目笔记】01项目介绍

一、技术框架 1.后端服务 Spring Boot为主体框架 Spring MVC为Web框架 MyBatis、MyBatis Plus为持久层框架&#xff0c;负责数据库的读写 阿里云短信服务 2.存储服务 MySql redis缓存数据 MinIO为对象存储&#xff0c;存储非结构化数据&#xff08;图片、视频、音频&a…