v-rep--websocket接口

websocket是什么

V-REP 中的 Web Socket 是一种用于在 V-REP 和外部应用程序之间进行通信的协议和技术。Web Socket 基于 TCP 连接,可以提供双向、实时的数据传输,适用于互动性或实时交互性应用。

(比如v-rep在云服务器上运行,通过websocket和用户所使用的web前端通信)


什么是云仿真

就是将v-rep的仿真程序发送到云服务器上,借助云服务器更好的硬件设备更高效地运行v-rep程序,用户可以从云服务器上获取需要的v-rep数据。

使用云仿真是将 V-REP 的仿真环境迁移到云端,让 V-REP 在云服务器上进行运行,用户通过互联网,通过浏览器等远程接入云端的 V-REP环境来完成仿真操作。因此,使用云仿真不需要将 V-REP 的程序发送到云服务器上运行,而是将 V-REP 的仿真环境放到云端进行运行,用户可以通过互联网访问云端的 V-REP 环境,进行仿真任务,而不需要在本地计算机上安装和配置 V-REP 软件。
 

什么是云端

云端(Cloud)指的是互联网上的远程服务器,也被成为“云服务器”,是封装计算资源的虚拟化环境。云端提供了一个集中式的存储、管理和运行数据和应用程序的平台,用户可以通过互联网访问这些数据和应用程序。

《互联网上用于管理,存储,运行数据的服务器》

websocket在v-rep中的作用

完成云服务器上v-rep仿真和web浏览器之间的通信。

websocket的实现

v-rep内部websocket实现(服务端)

wsRemoteAPI

源码链接

sim = require 'sim'
removeLazyLoaders()

wsRemoteApi = {}
//获取wsRemoteApi.verbose这个v-rep全局参数的值,无值返回0
function wsRemoteApi.verbose()
    return sim.getNamedInt32Param('wsRemoteApi.verbose') or 0
end

function wsRemoteApi.require(name)
    _G[name] = require(name)
end

function wsRemoteApi.info(obj)
    if type(obj) == 'string' then obj = wsRemoteApi.getField(obj) end
    if type(obj) ~= 'table' then return obj end
//~=  :表示不等于
    local ret = {}
    for k, v in pairs(obj) do
        if type(v) == 'table' then
            ret[k] = wsRemoteApi.info(v)
        elseif type(v) == 'function' then
            ret[k] = {func = {}}
        elseif type(v) ~= 'function' then
            ret[k] = {const = v}
        end
    end
    return ret
end
/*
该函数接受一个字符串类型的参数 `f`,表示要获取的值的键。在 Lua 语言中,字符串类似于表中的字段名,可以作为表索引来访问对应的值。例如,`_G['print']` 可以获取 Lua 语言中的 `print` 函数。

在函数体内部,首先将 `_G` 赋值给变量 `v`,表示从全局变量表开始查找。然后通过 `string.gmatch` 函数循环遍历字符串类型的键 `f` 中所有的单词和下划线,以及它们出现的顺序。

在每次循环中,根据单词获取表 `v` 中对应的值,并将其赋值给变量 `v`。如果在遍历的过程中遇到了 `v` 为空(`nil`)的情况,则说明字符串类型的键在 `_G` 全局变量表中不存在,于是返回 `nil`。最后返回变量 `v`,表示找到了对应的值,并将其返回。
*/
//获取key(f)对应的value
function wsRemoteApi.getField(f)
    local v = _G
    for w in string.gmatch(f, '[%w_]+') do
        v = v[w]
        if not v then return nil end
    end
    return v
end

function wsRemoteApi.handleRequest(req)
    if wsRemoteApi.verbose() > 1 then print('request received:', req) end
    local resp = {}
    resp['id'] = req['id']
    if req['func'] ~= nil and req['func'] ~= '' then
        local func = wsRemoteApi.getField(req['func'])
        local args = req['args'] or {}
        if not func then
            resp['error'] = 'No such function: ' .. req['func']
        else
            local status, retvals = pcall(
                                        function()
                    local ret = {func(unpack(args))}
                    return ret
                end
                                    )
            resp[status and 'ret' or 'error'] = retvals
        end
    elseif req['eval'] ~= nil and req['eval'] ~= '' then
        local status, retvals = pcall(
                                    function()
                local ret = {loadstring('return ' .. req['eval'])()}
                return ret
            end
                                )
        resp[status and 'ret' or 'error'] = retvals
    end
    resp['success'] = resp['error'] == nil
    if wsRemoteApi.verbose() > 1 then print('returning response:', resp) end
    return resp
end

function onWSMessage(server, connection, message)
    local rawReq = message

    -- if first byte is '{', it *might* be a JSON payload
    if rawReq:byte(1) == 123 then
        local req, ln, err = json.decode(rawReq)
        if req ~= nil then
            local resp = wsRemoteApi.handleRequest(req)
            resp = json.encode(resp)
            simWS.send(server, connection, resp, simWS.opcode.text)
            return
        end
    end

    -- if we are here, it should be a CBOR payload
    local status, req = pcall(cbor.decode, rawReq)
    if status then
        local resp = wsRemoteApi.handleRequest(req)
        resp = cbor.encode(resp)
        -- resp=sim.packTable(resp,1)
        simWS.send(server, connection, resp, simWS.opcode.binary)
        return
    end

    sim.addLog(sim.verbosity_errors, 'cannot decode message: no suitable decoder')
    return ''
end

function wsRemoteApi.publishStepCount()
    -- if wsRemoteApi.verbose()>1 then
    --    print('publishing simulationTimeStepCount='..simulationTimeStepCount)
    -- end
end

function sysCall_info()
    return {
        autoStart = sim.getNamedBoolParam('wsRemoteApi.autoStart') ~= false,
        menu = 'Connectivity\nWebSocket remote API server',
    }
end

function sysCall_init()
    simWS = require 'simWS'
    port = sim.getNamedInt32Param('wsRemoteApi.port') or 23050
    if wsRemoteApi.verbose() > 0 then
        sim.addLog(
            sim.verbosity_scriptinfos,
            string.format('WebSocket Remote API server starting (port=%d)...', port)
        )
    end
    json = require 'dkjson'
    -- cbor=require 'cbor' -- encodes strings as buffers, always. DO NOT USE!!
    cbor = require 'org.conman.cbor'
    wsServer = simWS.start(port)
    simWS.setMessageHandler(wsServer, 'onWSMessage')
    if wsRemoteApi.verbose() > 0 then
        sim.addLog(sim.verbosity_scriptinfos, 'WebSocket Remote API server started')
    end
    stepping = false
end

function sysCall_cleanup()
    if not simWS then return end
    if wsServer then simWS.stop(wsServer) end
    if wsRemoteApi.verbose() > 0 then
        sim.addLog(sim.verbosity_scriptinfos, 'WebSocket Remote API server stopped')
    end
end

function sysCall_addOnScriptSuspend()
    return {cmd = 'cleanup'}
end

function sysCall_addOnScriptSuspended()
    return {cmd = 'cleanup'}
end

function sysCall_nonSimulation()
end

function sysCall_beforeMainScript()
    local outData
    if stepping then
        outData = {doNotRunMainScript = not go}
        go = nil
    end
    return outData
end

function sysCall_beforeSimulation()
    simulationTimeStepCount = 0
    wsRemoteApi.publishStepCount()
end

function sysCall_actuation()
    simulationTimeStepCount = simulationTimeStepCount + 1
    wsRemoteApi.publishStepCount()
end

function sysCall_afterSimulation()
    stepping = false -- auto disable sync. mode
end

function setStepping(enable)
    stepping = enable
    go = nil
end

function step()
    go = true
end

wsRemoteAPI中的接口sysCall_init()调用simWS的start接口建立连接。

那么sysCall_init什么时候被执行呢?

v-rep启动的时候就会自动启动连接的监听。

simWS

源码链接

从这个插件的start函数中可以看出,调用start,server端就会listen,然后accept,建立连接。

服务端代码启动流程

1,监听启动

1-1,v-rep启动----调用wsRemoteAPI中的接口sysCall_init(),其中调用simWS的start接口监听,建立连接。

2,事件监听启动

onInstancePass中调用webSocket::server对象的poll接口进行事件监听。

onInstance由v-rep自动调用。

verbose

在 V-REP 中,`wsRemoteApi.verbose()` 函数用于设置或获取远程 API 调用时的日志输出级别。日志输出级别是一个整数值,决定了在进行远程 API 调用时打印哪些日志信息,以便于调试和问题定位。

常见的远程 API 日志输出级别如下:

- 0:不输出任何信息;
- 1:输出仅关键信息,如连接建立和断开等;
- 2:输出详细调用信息,如函数名、参数等;
- 3:输出所有信息,包括调试和错误信息。

浏览器前端websocket实现和接口调用(客户端)

前端怎么打开网页

html双击就会自动使用浏览器打开,浏览器打开就会自动执行html。

(选择Edge浏览器快一些)

客户端代码启动流程

前端页面显示肯定是通过加载html文件,通过解析html文件显示页面的。

前端通过在html中切入js语言,浏览器自动解析并执行。

client端(前端)建立连接只需要两步

1,建立RemoteAPIClient对象;

2,调用RemoteAPIClient中的WebSocketAsPromised对象的open接口发起连接。

前端html中的js建立RemoteAPIClient对象,调用对象open()发起和server的连接,利用这个对象---和服务端建立连接和通信。

        <script>
            const log = (what) => $('#log').append(`${what}\n`);
            (async () => {
                var client = new RemoteAPIClient('localhost', 23050, 'json');
                log('Connecting...');
                await client.websocket.open();
                log('Getting proxy object "sim"...');
                var sim = await client.require('sim');
                log('Calling sim.getObject("/Floor")...');
                var [h] = await sim.getObject('/Floor');
                log(`Result: ${h}`);
            })();
        </script>

client端事件发送

RemoteAPIClient对象中的call接口调用WebScoketAsPromised对象的sendRequest接口发送数据,并等待server端执行返回执行结果数据。

 RemoteAPIClient
"use strict";

const WebSocketAsPromised = require('websocket-as-promised');

class RemoteAPIClient {
    //编解码方式(默认为 'cbor')
    constructor(host = 'localhost', port = 23050, codec = "cbor", opts = {}) {
        this.host = host;
        this.port = port;
        this.codec = codec;
        var packMessage;
        var unpackMessage;
        /*
        则使用 CBOR 序列化和反序列化库 `CBOR.encode` 和 `CBOR.decode`
         进行编解码。`packMessage` 为一个函数,将传入的数据进行 CBOR 编码,
         并返回编码后的结果。`unpackMessage` 为一个异步函数,将传入的数据进
         行 CBOR 解码,并返回解码后的结果。

         如果编解码方式为 `'json'`,则使用 JavaScript 原生的 JSON 序列化和
         反序列化函数 `JSON.stringify` 和 `JSON.parse` 进行编解码。
        */
        if(this.codec == 'cbor') {
            //this.websocket.binaryType = "arraybuffer";
            packMessage = data => CBOR.encode(data);
            unpackMessage = async data => CBOR.decode(await data.arrayBuffer());
        } else if(this.codec == "json") {
            packMessage = data => JSON.stringify(data);
            unpackMessage = data => JSON.parse(data);
        }
        var wsOpts = {
            packMessage,
            unpackMessage,
            // attach requestId to message as `id` field
            attachRequestId: (data, requestId) => Object.assign({id: requestId}, data),
            // read requestId from message `id` field
            extractRequestId: data => data && data.id,
        };
        for(var k in opts)
            wsOpts[k] = opts[k];
        this.websocket = new WebSocketAsPromised(`ws://${this.host}:${this.port}`, wsOpts);
    }
/*
使用 `await` 关键字等待该 Promise 对象执行完成并获取响应结果,保存在变量
 `reply` 中。
 在该方法中,使用了 `async` 关键字将 `call` 方法标记为异步函数,使其返回一个 
 Promise 对象。在调用 `await` 时,控制权会交给引擎,等待 WebSocket 通信的异
 步操作完成,并返回一个响应结果
*/
//函数调用,传递函数名和参数
    async call(func, args) {
        var reply = await this.websocket.sendRequest({func, args});
        if(reply.success) {
            return reply.ret;
        } else {
            throw reply.error;
        }
    }
/*
返回name所对应的值,name可能是一个普通变量,也可能是一个建值对的key,或者其他
js对象
*/
    async getObject(name) {
        var r = await this.call('wsRemoteApi.info', [name]);
        return this.getObject_(name, r[0]);
    }

    async require(name) {
        await this.call('wsRemoteApi.require', [name]);
        return await this.getObject(name);
    }

    getObject_(name, _info) {
        const client = this;
        var ret = {}
        for(let k in _info) {
            var v = _info[k];
            if(Object.keys(v).length == 1 && v['func'] !== undefined)
                ret[k] = async function(...args) {
                    return await client.call(name + "." + k, args);
                };
            else if(Object.keys(v).length == 1 && v['const'] !== undefined)
                ret[k] = v['const'];
            else
                ret[k] = this.getObject(name + "." + k, null, null, v);
        }
        return ret
    }
}
WebSocketAsPromised


`WebSocketAsPromised` 是一个第三方 JavaScript 库,用于实现基于 Promise 的 WebSocket 连接。
标准的 WebSocket API 使用回调函数来处理事件,例如在连接建立时调用 `onopen` 回调函数,在收到消息时调用 `onmessage` 回调函数等。而使用 `WebSocketAsPromised` 库可以直接返回 Promise 对象来处理 WebSocket 相关的操作,这种写法更符合现代 JavaScript 中基于 Promise 或 async/await 的编程风格,更易于编写和维护。
在这段代码中,`this.websocket` 保存了一个 `WebSocketAsPromised` 类型的对象,表示当前客户端的 WebSocket 连接。`WebSocketAsPromised` 的构造函数需要传递两个参数:WebSocket 的 URL 和 WebSocket 配置对象。其中,URL 参数表示要连接的 WebSocket 服务器的地址和端口号,`wsOpts` 参数为可选参数对象,用于配置 WebSocket 的一些选项,如超时时间、心跳间隔等。
通过创建基于 Promise 的 `WebSocketAsPromised` 类型的对象,可以使用 `async/await` 等方式来处理 WebSocket 连接的事件处理和错误处理,让代码更加简洁、易读和可维护。

open()函数的作用

用于client对端发起连接,和远程server建立连接。

        <script>
            const log = (what) => $('#log').append(`${what}\n`);
            (async () => {
                var client = new RemoteAPIClient('localhost', 23050, 'json');
                log('Connecting...');
                await client.websocket.open();
                log('Getting proxy object "sim"...');
                var sim = await client.require('sim');
                log('Calling sim.getObject("/Floor")...');
                var [h] = await sim.getObject('/Floor');
                log(`Result: ${h}`);
            })();
        </script>
如果open连接失败

如果`open()`连接失败,`open()` 后面的代码不会执行,而是会抛出异常。在这个案例中,如果`await client.websocket.open()`连接失败,控制台会输出一个错误或异常信息,即不会输出"Getting proxy object "sim"..."或"Result: ${h}"。

这是因为`await`关键字会等待异步方法的执行结果,如果异步方法出现错误或异常,则会阻塞当前线程并将错误或异常抛出,因此,如果`open()`连接失败,则异步 `async () => {...}` 函数的执行会被中止,后续的代码也不会执行。

对于上面的代码,如果server端没打开,client端一直处于Connecting
 

websocketpp

pp---cpp

websocket提供了封装好了client和server从链接建立,数据监听,通信到结束通信的对象和接口。

资料链接

讲解

用户手册

html和js

一般情况下,前端加载 HTML 文件时,其中的 JavaScript 代码就会被自动执行。这是因为 HTML 中的 `<script>` 标签会被浏览器自动解析并执行其中的 JavaScript 代码

当浏览器解析 HTML 文件时,碰到 `<script>` 标签时会自动执行其中的脚本。如果 `<script>` 标签中带有 `src` 属性,则浏览器会根据该属性的值加载外部 JavaScript 文件,并自动执行其中的代码。如果 `<script>` 标签内部有 JavaScript 代码,则直接执行其中的代码。

需要注意的是,当浏览器加载 JS 文件时,会阻塞 HTML 页面的渲染。如果 JavaScript 代码很长或运行时间很长,可能会导致页面出现卡顿的现象。为了避免这种情况,可以将 JavaScript 代码放到页面底部,在 HTML 元素加载完毕后再执行。另外,也可以使用异步加载技术,如 `<script async src="xxx.js"></script>` 让 JS 文件在后台异步加载,避免阻塞页面渲染。
 

eg:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>CoppeliaSim remote API client</title>
    </head>
    <body>
        <div id="log" style="white-space: pre"></div>
        <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/gh/spaceify/cbor-js@master/cbor.js" integrity="sha512-0ABB8mRQj73e8+aaUzonPYnP34/YsUCf6SGUJp/pj5BUXttDonDIvCI7XuC7C27Qem6yRpzIzTlq8kJSlUNjoQ==" crossorigin="anonymous"></script>
        <script src="WebSocketAsPromised.bundle.js"></script>
        <script src="RemoteAPIClient.js"></script>
        <script>
            const log = (what) => $('#log').append(`${what}\n`);
            (async () => {
                var client = new RemoteAPIClient('localhost', 23050, 'json');
                log('Connecting...');
                await client.websocket.open();
                log('Getting proxy object "sim"...');
                var sim = await client.require('sim');
                log('Calling sim.getObject("/Floor")...');
                var [h] = await sim.getObject('/Floor');
                log(`Result: ${h}`);
            })();
        </script>
    </body>
</html>

这是一个基于 JavaScript 的 V-REP 远程 API 客户端示例,用于在网页中通过 JavaScript 调用 V-REP 中的场景对象和函数。

在代码中,首先定义了一个 `log` 函数,用于在页面上输出调试信息。然后使用 `async` 函数和箭头函数等语法定义了一个立即执行的异步函数,其中包含了调用 V-REP 远程 API 的过程。

在异步函数中,首先创建了一个名为 `client` 的 `RemoteAPIClient` 对象,用于与 V-REP 中的远程 API 服务建立连接。其中 `localhost` 表示连接本地计算机,`23050` 表示连接的端口号,`json` 表示使用 JSON-RPC 协议进行通信。

然后使用 `client.require('sim')` 函数获取到远程 API 的命名空间 `sim`,该命名空间包含了 V-REP 中预定义的各种对象和函数。最后使用 `sim.getObject('/Floor')` 函数获取到名为 `/Floor` 的场景对象,将结果保存到变量 `h` 中。

在获取到结果后,调用 `log` 函数将结果输出到页面上。

js调用加载lua模块,调用lua接口实现及原理

最终的实现是通过三方库定义的WebSocketAsPromised接口sendRequest()向服务端发送需要调用的接口和参数,服务端接收到请求之后,会执行需要调用的接口,并返回执行接口返回的内容。

因为我们v-rep中的RemoteAPIClient指定了序列化和反序列化,所以即使调用Lua或者c++接口,反序列化之后就可以变为js所对应的数据。

class RemoteAPIClient {
    //编解码方式(默认为 'cbor')
    constructor(host = 'localhost', port = 23050, codec = "cbor", opts = {}) {
        this.host = host;
        this.port = port;
        this.codec = codec;
        var packMessage;
        var unpackMessage;
        /*
        则使用 CBOR 序列化和反序列化库 `CBOR.encode` 和 `CBOR.decode`
         进行编解码。`packMessage` 为一个函数,将传入的数据进行 CBOR 编码,
         并返回编码后的结果。`unpackMessage` 为一个异步函数,将传入的数据进
         行 CBOR 解码,并返回解码后的结果。

         如果编解码方式为 `'json'`,则使用 JavaScript 原生的 JSON 序列化和
         反序列化函数 `JSON.stringify` 和 `JSON.parse` 进行编解码。
         
        数据传输格式使用json,无论数据来自lua函数返回还是c++函数返回,JSON.parse都解析为
        js数据。
        */
        if(this.codec == 'cbor') {
            //this.websocket.binaryType = "arraybuffer";
            packMessage = data => CBOR.encode(data);
            unpackMessage = async data => CBOR.decode(await data.arrayBuffer());
        } else if(this.codec == "json") {
            packMessage = data => JSON.stringify(data);
            unpackMessage = data => JSON.parse(data);
        }
        var wsOpts = {
            packMessage,
            unpackMessage,
            // attach requestId to message as `id` field
            attachRequestId: (data, requestId) => Object.assign({id: requestId}, data),
            // read requestId from message `id` field
            extractRequestId: data => data && data.id,
        };
        for(var k in opts)
            wsOpts[k] = opts[k];
        this.websocket = new WebSocketAsPromised(`ws://${this.host}:${this.port}`, wsOpts);
    }


 

客户端怎么调用接口的

通过html中执行js代码。

方式1:先加载模块,再通过模块加载模块中定义的接口。

插件中的返回值通过js获取

直接在js中定义与调用的函数返回的类型对应的js变量接收返回值即可。

                
                //getInfo返回数组
                var [info]=await simTest.getInfo();
                log(`info length: ${info.length}`);
                for(var i=0;i<info.length;++i){
                    log(`getInfo: ${info[i]}`);
                }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Groovy(第五节) Groovy 之集合

Groovy 可以直接在语言内使用集合。在 Groovy 中,不需要导入专门的类,也不需要初始化对象。集合是语言本身的本地成员。Groovy 也使集合(或者列表)的操作变得非常容易,为增加和删除项提供了直观的帮助。 可以将范围当作集合 在前一节学习了如何用 Groovy 的范围将循环变得…

vue - - - - - vue3使用draggable拖拽组件

vue3使用draggable拖拽组件 一、组件安装二、插件使用三、遇到的问题1. missing required prop&#xff1a; “itemKey” 一、组件安装 yarn add vuedraggablenext // or npm i -S vuedraggablenext二、插件使用 <template><draggableitem-key"id"class&q…

【HDFS】Decommision(退役) EC数据节点剩最后几个块卡住的问题

一、背景 近期操作退役EC集群的节点。在退役的过程中,遇到了一些问题。特此总结一下。 本文描述的问题现象是: 每一批次退役10个节点,完全退役成功后开始操作下一批。 但是,中间有一批次有2台节点的Under Replicated Blocks一直是1,不往下降。 处于Decommissioning状态卡…

三款热门超声波清洗机对比测评:希亦、固特、大宇多维度实测!

如果你非常在意物品的健康卫生&#xff0c;并且希望能够摆脱手动清洗一些物品而彻底解放双手&#xff01;在家备一款超声波清洗机还是非常有必要的&#xff01;无论是珠宝、眼镜还是日常小物&#xff0c;都希望能够保持如新的光泽和卫生状态。那么超声波清洗机是最合适不过的&a…

【Leetcode每日一题】二分查找 - 有效的完全平方数(难度⭐)(19)

1. 题目解析 Leetcode链接&#xff1a;367. 有效的完全平方数 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于判断给定的整数是否可以开方成两个整数相乘&#xff0c;可以就返回false&#xff0c;反之返回true。 2. 算法…

es安装中文分词器 IK

1.下载 https://github.com/medcl/elasticsearch-analysis-ik 这个是官方的下载地址&#xff0c;下载跟自己es版本对应的即可 那么需要下载 7.12.0版本的分词器 2.安装 1.在es的 plugins 的文件夹下先创建一个ik目录 bash cd /home/apps/elasticsearch/plugins/ mkdir ik …

Spring Web 过滤器使用常见错误(上)

我们都知道&#xff0c;过滤器是 Servlet 的重要标准之一&#xff0c;其在请求和响应的统一处理、访问日志记录、请求权限审核等方面都有着不可替代的作用。在 Spring 编程中&#xff0c;我们主要就是配合使用ServletComponentScan 和 WebFilter 这两个注解来构建过滤器。 说起…

java 反射机制 (一)

java反射机制&#xff1a; 即通过外部文件配置&#xff0c;不修改文件源码的情况下&#xff0c;来控制程序&#xff0c;也符合设计模式的OCP原则&#xff08;开闭原则&#xff1a;不修改源码&#xff0c;扩容原则&#xff09; Java Reflection 1.反射机制允许程序在执行期间…

阿里云OSS对象存储的使用和实现万能文件上传

文章目录 阿里云OSS对象存储的使用和实现万能文件上传1、开通阿里云OSS对象存储服务&#xff08;新用户可以免费试用三个月&#xff09;1.1、点击免费试用并选择自己想要使用的服务1.2、咱们这里选择使用第一个存储服务&#xff0c;然后点击立即试用 2、创建存储空间&#xff0…

IP源防攻击IPSG(IP Source Guard)

IP源防攻击IPSG&#xff08;IP Source Guard&#xff09;是一种基于二层接口的源IP地址过滤技术&#xff0c;它能够防止恶意主机伪造合法主机的IP地址来仿冒合法主机&#xff0c;还能确保非授权主机不能通过自己指定IP地址的方式来访问网络或攻击网络。 2.1 IPSG基本原理 绑定…

进制转换md5绕过 [安洵杯 2019]easy_web1

打开题目 在查看url的时候得到了一串类似编码的东西&#xff0c;源码那里也是一堆base64&#xff0c;但是转换成图片就是网页上我们看见的那个表情包 ?imgTXpVek5UTTFNbVUzTURabE5qYz0&cmd 我们可以先试把前面的img那串解码了 解码的时候发现长度不够&#xff0c;那我们…

三、软考-系统架构设计师笔记-计算机系统基础知识

计算机系统概述 计算机系统是指用于数据管理的计算机硬件、软件及网络组成的系统。 它是按人的要求接收和存储信息&#xff0c;自动进行数据处理和计算&#xff0c;并输出结果信息的机器系统。 冯诺依曼体系计算机结构&#xff1a; 1、计算机硬件组成 冯诺依曼计算机结构将…

PDN分析及应用系列二-简单5V电源分配-Altium Designer仿真分析-AD

PDN分析及应用系列二 —— 案例1:简单5V电源分配 预模拟DC网络识别 当最初为PCB设计打开PDN分析仪时,它将尝试根据公共电源网络命名法从设计中识别所有直流电源网络。 正确的DC网络识别对于获得最准确的模拟结果非常重要。 在示例项目中已经识别出主DC网络以简化该过程。 …

Centos7:自动化配置vim | suoders信任列表添加普通用户

Centos7&#xff1a;自动化配置vim | suoders信任列表添加普通用户 vim 配置原理sudoers系统可信任列表中添加普通用户自动化配置vim vim 配置原理 在目录/etc下有一个vimrc文件&#xff0c;该文件是系统中公共的vim配置文件&#xff0c;对所有用户都成立。  而在每个普通用户…

新品发布 | Ftrans CDS 跨域文件交换集中管控系统

1、背景 现如今&#xff0c;随着经济的快速发展&#xff0c;越来越多的企业架构呈现分散的状态&#xff0c;企业在异国、异地设立分支机构&#xff0c;在日常经营中&#xff0c;企业总部和分支机构间存在平行、垂直及互相交叉的管理模式和业务往来需求&#xff0c;因此&#x…

从0到1实现五子棋游戏!!

Hello&#xff0c;好久不见宝子们&#xff0c;今天来给大家更一个五子棋的程序~ 我们今天要讲的内容如下&#xff1a; 文章目录 1.五子棋游戏介绍1.1 游戏玩法介绍&#xff1a; 2.准备工作2.1 具体操作流程 3.游戏程序主函数4.初始化棋盘4.1.定义宏变量4.2 初始化棋盘 5.打印…

微软广告和网络服务CEO承认OpenAI的Sora将加入Copilot,但需要一些时间

事情的起因是一名网友询问 Sora 是否会加入 Copilot&#xff0c;微软广告和网络服务CEO首席执行官——Mikhail Parakhin 回应说&#xff1a;“最终&#xff0c;但这需要时间。”毕竟投了几十个亿美金进去&#xff0c;不亏是金主爸爸。 图为Mikhail Parakhin Sora是OpenAI开发的…

Socket网络编程(二)——UDP快速入门

目录 UDP相关概念UDP是什么为什么不可靠UDP能做什么UDP包最大长度 UDP单播、广播、多播概念1. 单播、广播、多播模型图2. ip地址分类3. 子网掩码的作用&#xff1a;4. 广播地址5. 网段划分6. 变长子网掩码 UDP核心APIAPI-DatagramSocketDatagramSocket构造方法DatagramSocket常…

疑似某免杀测试样本被国外安全团队捕获

今天笔者发现国外MalwareHunterTeam捕获到一例特殊的样本&#xff0c;如下所示&#xff1a; 服务器的IP地址为:117.50.106.161&#xff0c;同时样本的PDB信息&#xff0c;如下所示&#xff1a; 样本的PDB信息&#xff1a;C:\Users\Xiaowu\source\repos\bypass-1\Release\bypass…

解决vscode内置视图npm脚本操作报权限问题

项目背景 当我们使用 vscode 运行NPM脚本时却爆红了&#xff0c;提示系统上禁止运行脚本。 解决思路 竟然提示权限不够&#xff0c;那么咱们就从系统权限出发&#xff0c;vscode右键以管理员身份运行 在集成终端中输入一下命令 # get-executionpolicy是PowerShell中的命令,用…