很多系统都自带邮件服务器,比如最常见的办公系统。一般邮件服务器都建立在Linux设备上,但是杀毒软件往往很少有支持Linux平台的,即使支持,操作往往也很麻烦或者需要图形界面,而人们一般不会再邮件服务器上特意去装一个图形界面的。所以不妨换个思路,在局域网中再来几台Windows设备,装上杀毒软件专门提供病毒检测服务。邮件服务器把需要检测的文件发送给Windows杀毒服务器进行扫描,获得一个扫描结果后入库。Windows服务器和邮件服务器不共享存储,虽然降低了效率但是安全性保密性得到提高。而且邮件附件不会每天都去扫一遍,发邮件的时候实时扫描就可以了。对于小规模的邮件服务器非常方便,搭建成本极低,也就是买个服务器的成本。要是虚拟化平台可以直接打到零成本部署杀毒服务器。

一、基于卡巴斯基免费版命令行使用说明

测试了国内国外很多杀毒软件,包括收费的和免费的。这里要隆重表扬一下卡巴斯基,在大多数杀毒大厂都设为收费服务的命令行查毒工具卡巴斯基竟然在他的免费版本里提供了。这个命令行查毒工具是邮件服务器的核心,卡巴斯基真乃良心企业。

首先到卡巴斯基官网下载最新的免费版,当然你要下收费版更好。https://www.kaspersky.com.cn/free-antivirus

我下载的版本是kfa18.0.0.405abzh-hans_12797.exe

安装完毕是这个样子的,就是普通的家用版,然而我们现在要把它当成服务器级别的来使用了。

重要的是卡巴斯基安装目录下的命令行杀毒程序,他的位置是C:\Program Files (x86)\Kaspersky Lab\Kaspersky Free 18.0.0\avp.com,几乎所有的Windows电脑都只能安装在这个位置。

然后我们使用命令行尝试一下查杀功能,注意,如果你电脑上卡巴斯基程序没有运行的话,那么执行avp.com会开启卡巴斯基防护服务和图形界面

avp.com SCAN 文件或文件夹路径
注意如果你参数是文件路径那么就只扫描这一个文件,如果填的是文件夹路径那么就会递归搜索这个文件夹下所有的文件,但是不支持通配符,比如*.rar,2017.*这样的文件名。另外还需要注意windows cmd程序不支持路径中间有空格,需要用双引号把路径包起来,下面分别是扫描单个文件和扫描文件夹

可以看出卡巴斯基把文件扫描的具体清单打印了出来,包括扫描的哪个文件,这个文件是不是ok,最下面有一个总扫描文件数,总安全文件数和被发现病毒文件数。在读取报文的时候我们可以先检查总病毒文件数是不是为0,如果不为0再向上寻找是哪个文件没有检测通过。

注意:有些文件虽然只是单个文件,但是卡巴斯基会拆成一块一块的扫描,典型的就是zip,rar等压缩文件,exe安装包,Word Excel等办公文件,如下图只扫描了一个excel文。件但是他扫描了4个,估计把工作簿里每一个sheet都算做一个文件。很多时候word文档能扫描出30多个文件

中文出现乱码是很正常的事,不会影响扫描结果。

1.1 NodeJS服务器调用卡巴斯基过程说明

既然有了这么好用的命令行工具,那么我们找一个中间件,对外提供一个可访问的接口,让其他服务器把要查毒的文件上传上来,然后扫描完把这个报文发送回去,让其他的服务器自己去解析报文各取所需就好了,报文格式就是上面的截图所示案例,一般如下

AV bases release date: 2017-09-15 19:55:00 (full)
; --- Settings ---
; Action on detect:     Ask after scan
; Scan objects: All objects
; Use iChecker: Yes
; Use iSwift:   Yes
; Try disinfect:        Yes
; Try delete:   Yes
; Try delete container: No
; Exclude by mask:      No
; Include by mask:      No
; Objects to scan:
;       "E:\54\"        Enable = Yes    Recursive = Yes
; ------------------
2017-09-16 15:58:01     Scan_Objects$0320         starting   1%
2017-09-16 15:58:01     E:\54\Save003.sav       ok
2017-09-16 15:58:01     Scan_Objects$0320         running    1%
2017-09-16 15:58:01     E:\54\saves.ini ok
2017-09-16 15:58:01     E:\54\Save001.sav       ok
2017-09-16 15:58:01     E:\54\Save002.sav       ok
2017-09-16 15:58:01     Scan_Objects$0320         completed
Info: task 'ods' finished, last error code 0
;  --- Statistics ---
; Time Start:   2017-09-16 15:58:01
; Time Finish:  2017-09-16 15:58:01
; Processed objects:    4
; Total OK:     4
; Total detected:       0
; Suspicions:   0
; Total skipped:        0
; Password protected:   0
; Corrupted:    0
; Errors:       0
;  ------------------

注意尽量不要使用中文文件名,不然在文件夹内一次扫描多个文件时因为乱码不知道哪个文件有毒,但是每次都使用单文件扫描就不会有这个问题了。

中间件这里不选大佬级的Apache或者Tomcat,用个小规模高效率服务器就好,我这里使用nodeJS,因为程序写起来太简短了,搭建一个杀毒服务器只需不到100行代码即可搞定。

首先确保你电脑上已经部署了node和express框架,如果不会安装出门左拐上百度,然后程序主文件如下写法,下面这个例子是单文件扫描,就是客户端每次只上传一个文件进行扫描。注意在服务器调用的时候加上了/i0参数,目的是不让它自动询问或清除带毒文件,只做扫描即可。以免询问过程卡住进程。

index.js

var express = require('express');
var app = express();
var upload = require('./fileupload');
app.use(express.static('html'));var process = require('child_process');var anvirusSoftware = '"C:\\Program Files (x86)\\Kaspersky Lab\\Kaspersky Free 18.0.0\\avp.com" SCAN /i0 '//文件上传服务
app.post('/upload', upload.single('virus_file'), function (req, res, next) {console.log('上传来的文件是:'+req.file);if (req.file) {//res.send('文件上传成功');console.log(req.file);var upload_directory = req.file.destination;var path = req.file.path;console.log('上传文件被存储到了目标文件夹:'+upload_directory);console.log('被保存的文件路径:'+upload_directory);console.log('=======');console.log(req.body);console.log("准备开启杀毒程序")process.exec(anvirusSoftware + path,function (error, stdout, stderr) {if (error !== null) {console.log('exec error: ' + error);} else if (stdout !== null){res.send(stdout);console.log('success: ' + stdout);}});} else {res.send('没有上传任何文件');}
});
app.get('/upload', function (req, res, next) {console.log('get来了'+req.file);res.send('不要用get请求');
});
app.get('/', function (req, res) {res.send('Hello World!');
});var server = app.listen(3000, function () {var host = server.address().address;var port = server.address().port;console.log('Example app listening at http://%s:%s', host, port);
});

其中<input>的name属性在upload.single中确定,本例是“virus_file”
客户端使用POST进行上传,服务器地址为127.0.0.1:3000并监听全部网卡的3000端口,你可以自己配置。这里用到了nodeJS的文件上传模块,专门写了一个文件用来配置multer ,这个文件配置了上传后文件存储的位置,文件存储的文件名等信息,返回值是个multer实例

fileupload.js

var multer = require('multer');
var dstPath = process.cwd() + '/uploads';//设置上传文件路径
var storage = multer.diskStorage({//Note:如果destination:传递的是一个函数,你负责创建文件夹,如果你传递的是一个字符串,multer会自动创建destination: dstPath,//TODO:文件区分目录存放//给上传文件重命名filename: function (req, file, cb) {cb(null, '收到的文件_'+file.originalname);}
});//添加配置文件到muler对象。
var upload = multer({storage: storage,//其他设置请参考multer的limits//limits:{}
});
//导出对象
module.exports = upload;

另外再展示一下依赖文件Package.json,命令行使用npm install就可以自动联网下载依赖包

{"name": "anti_virus","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "","license": "ISC","dependencies": {"child_process": "^1.0.2","express": "^4.15.4","multer": "^1.3.0"}
}

其中child_process是用来新开进程执行cmd命令的依赖库,multer是执行文件存储接收的依赖库。

短短几行一个杀毒服务器就搭建好啦

为了测试方便,我们写一个简单的前端页面,真正使用的时候一般是Java或者PHP直接上传的。注意这里的input name属性要写和上面index.js规定的一样,为“virus_file”

<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form id='editfile' method='post' action='/upload' enctype='multipart/form-data'>选择要扫描的文件:<input name="virus_file"  type='file'/></br><input type='submit' value='提交'/>
</form>
</body>

然后命令行cd到我们node程序的文件夹,执行node index.js启动服务器,观察3000端口是否在监听状态,然后访问127.0.0.1:3000/test.html ,然后就可以选择文件然后点击提交,提交之后就会看见命令行输出上面的卡巴斯基的扫描过程,然后把最后结果反馈给浏览器

同时文件出现在了我们node app文件夹\uploads下,文件名为“收到的文件_”+原文件名,当然一般来说使用随机字母比较好

EDGE浏览器没有显示换行符,但是使用JAVA或PHP是没有什么问题的。nodeJS后台日志如下

这样我们就测试通过了。

1.2 多文件上传,批量扫描NodeJS配置

单个文件上传查毒可能会频繁地启动和关闭杀毒引擎,效率比较低,所以我们也可以设置一个多文件上传和杀毒的方案。他的核心是卡巴斯基对文件夹的扫描能力。

方法就是对于每一次上传文件请求,在NodeJS服务器上都单独建立一个文件夹,这个文件夹的名字是随机生成的,这个文件夹里存放本次请求上传的所有文件,查毒时只需要让卡巴斯基扫描这个文件夹就知道哪个文件有毒了。而且这样做同时发起的不同文件扫描请求不会冲突,结果准确,支持较大的并发量。

首先最重要的是修改fileupload.js这个文件,让它智能的对每个不同的request建立不同的文件夹,但是由于diskStorage这个方法每一个新上传的文件都会执行一次,关键在于如何区分当前这个文件是属于哪一个request的,毕竟同一时间我们的病毒服务器可能收到来自不同设备的好几个杀毒请求。

型号multer给出了req这个对象作为传入参数,所以我们为了方便识别当前文件的req是谁的req,我们可以在req这个对象内部放一个新成员“dir_name”,这个新成员是个随机数,对于一次上传多个文件来说,第一个被循环到的文件把这个随机数放入,并根据这个随机数建立本地的文件夹,然后后来的文件如果检查到这个随机数存在,那么就证明这一批文件是同一个request发来的,那么就放到刚才建立的哪个文件夹里。

/**** @Description 文件上传配置**/
var multer = require('multer');
var fs = require('fs');var dstPath = process.cwd() + '/uploads/';//设置上传文件路径var storage = multer.diskStorage({//Note:如果destination:传递的是一个函数,你负责创建文件夹,如果你传递的是一个字符串,multer会自动创建destination: function (req, file, cb) {console.log('req.dir_name===='+req.dir_name);var upload_dir = dstPath + req.dir_name;if(!req.dir_name){//如果这是这个req的第一个文件,还没有建立相关文件夹var dir_name = (Math.random()+"").slice(9);req.dir_name = dir_name;//标记这个requpload_dir = dstPath + dir_name;if (!fs.existsSync(upload_dir)) {fs.mkdirSync(upload_dir);console.log('创建文件夹成功:'+upload_dir);}}cb(null, upload_dir);},//TODO:文件区分目录存放//给上传文件重命名filename: function (req, file, cb) {cb(null, '收到的文件_'+file.originalname);}
});//添加配置文件到muler对象。
var upload = multer({storage: storage,//其他设置请参考multer的limits//limits:{}
});
//导出对象
module.exports = upload;
然后主入口文件也要做相应的修改,主要是把刚才的upload.single改成upload.array('属性名',最大文件上传数量),属性名还是要与<input>的name属性一致
var express = require('express');
var app = express();
app.use(express.static('html'));
var upload = require('./fileupload');var process = require('child_process');var anvirusSoftware = '"C:\\Program Files (x86)\\Kaspersky Lab\\Kaspersky Free 18.0.0\\avp.com" SCAN /i0 '//文件上传服务
app.post('/upload', upload.array('virus_file',10), function (req, res, next) {console.log(req.files);if (req.files) {//res.send('文件上传成功');var length = req.files.length;console.log('上传文件个数是:'+ length);var upload_directory = req.files[0].destination;console.log('上传文件被存储到了目标文件夹:'+upload_directory);for(var i=0;i<length;i++){var path = req.files[i].path;console.log('被保存的文件完整路径:'+path);}console.log('=======');console.log(req.body);console.log("准备开启杀毒程序");process.exec(anvirusSoftware + upload_directory ,function (error, stdout, stderr) {if (error !== null) {console.log('exec error: ' + error);} else if (stdout !== null){res.send(stdout);console.log('success: ' + stdout);}
});} else {res.send('没有上传任何文件');}
});
app.get('/upload', function (req, res, next) {console.log('get来了'+req.file);res.send('不要用get请求');
});
app.get('/', function (req, res) {res.send('Hello World!');
});var server = app.listen(3000, function () {var host = server.address().address;var port = server.address().port;console.log('Example app listening at http://%s:%s', host, port);
});

由于上面规定了最大可以上传10个文件,那么HTML测试页面也要小改一下

<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form id='editfile' method='post' action='/upload' enctype='multipart/form-data'>选择要扫描的文件:<input name="virus_file"  type='file'/></br>
选择要扫描的文件:<input name="virus_file"  type='file'/></br>
选择要扫描的文件:<input name="virus_file"  type='file'/></br>
选择要扫描的文件:<input name="virus_file"  type='file'/></br>
选择要扫描的文件:<input name="virus_file"  type='file'/></br><input type='submit' value='提交'/>
</form>
</body>

具体的项目结构和代码可以到github上下载:https://github.com/AlexZhuo/NodeScanVirus

此时我们既可以上传单个文件,也能上传多个文件,只要最大数量不超过上面index.js标记的就可以,而且也不需要从第一个input框开始,如我上面这样上传是没有问题的。点击提交之后会出现扫描结果的报文。可以看到是两个文件都进行了扫描(对于压缩文件可能会更多)

然后本次上传的文件被单独存储在一个uploads\466101518\下,如果再上传一次,那么就是另一个随机数文件夹里:

这样我们的反病毒服务器就搭建好了。

卡巴斯基其他命令行选项

另外卡巴斯基命令行还支持很多别的参数,执行avp.com HELP SCAN 结果如下,比如可以添加日志记录什么的,根据实际情况进行配置

C:\Program Files (x86)\Kaspersky Lab\Kaspersky Endpoint Security 10 for Windows SP1>avp.com HELP SCAN
Kaspersky Endpoint Security 10 for Windows (R) 10.2.4.674
(C) 2013 Kaspersky Lab ZAO. All rights reserved.Usage: SCAN [<files>] [/ALL][/MEMORY][/STARTUP][/MAIL][/REMDRIVES][/FIXDRIVES][/NETDRIVES][/QUARANTINE] [/@:<filelist.lst>][/i<0-4>] [-e:a|s|b|<filemask>|<seconds>][/R[A]:<report_file>] [/C:<settings_file>]SCAN /VLNS2 [/WUA][/WSUSCAB <wsus_file>] [<files>] [/lst <filelist.lst>]VLNS2 specific options:
/WUA               Scan with WUA (default: off)
/WSUSCAB           WSUS fileScan area:
<files>            List of files and/or folders delimited with space.Long path names must be enclosed in quotes.
/ALL               Scan my computer
/MEMORY            Scan computer memory
/STARTUP           Scan startup-objects
/MAIL              Scan mailboxes
/REMDRIVES         Scan removable media
/FIXDRIVES         Scan hard drives
/NETDRIVES         Scan network drives
/QUARANTINE        Scan quarantined objects
/@:<filelist.lst>  Scan files in specified list fileAction with infected files:
/i0                Report only
/i1                Disinfect object,skip if disinfection is impossible.
/i2                Disinfect object,delete object if disinfection is impossible,dont't delete objects from containers,delete containers with executable header.
/i3                Disinfect object,delete object if disinfection is impossible,delete containers if objects can not be deleted.
/i4                Delete infected objects,delete containers if objects can not be deleted.
/i8 (default)      Ask me immediately
/i9                Ask me when scan is finished
File types:
/fe                Quick check (by extensions)
/fi                Smart check (by format)r
/fa (default)      All files
Excludes:
-e:a               Skip archives
-e:b               Skip e-mail databases and plain text e-mail
-e:<filemask>      Skip files by mask
-e:<seconds>       Skip files scanned longer than <seconds>
-es:<size>         Skip files greater than <size in megabytes>
Reports:
/R:<report_file>   Save only critical events
/RA:<report_file>  Save all events
Additional settings:
/iChecker=<on|off> Enable/disable iChecker technology
/iSwift=<on|off>   Enable/disable iSwift technology
/C:<settings_file> Specifies configuration fileExamples:
avp.com SCAN /R:log.txt /MEMORY /STARTUP /MAIL "C:\Documents and Settings\All Users\My Documents" "C:\Program Files" C:\Downloads\test.exe
avp.com SCAN /MEMORY /@:objects2scan.txt /C:scan_settings.txt /RA:scan.log
avp.com SCAN /VLNS2
avp.com SCAN /VLNS2 /RA:scan.log /WUA C:\Windows\

二、Avast,AVG杀毒软件命令行扫描

另外再提一下,除了卡巴斯基有Windows下的命令行查毒工具之外,Avast,AVG杀毒软件也有,扫描速度要比卡巴斯基的快,但是是按照设备数和时间进行收费的。

Avast和AVG的目录结构和杀毒命令是一模一样的,如下ashCmd.exe就是专为命令行设计的工具,不过只能在收费版中看到这个文件。

运行杀毒也很简单,只是不像卡巴斯基那样有stdout输出,但是有一个图形界面,可以输出日志。不是很适合服务器调用,调用命令如下

C:\Program Files\AVAST Software\Avast>ashCmd.exe /SCAN D:\bilibili\

如果加上输出日志就能很清晰的看到具体扫描了哪些文件,每个文件的状态如何

C:\Program Files\AVAST Software\Avast>ashCmd.exe D:\bilibili\ /_ > C:\results.txt

日志内容如下

D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-1[高清版].mp4    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-2503[高清版].mp4    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-3812[高清版].mp4    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-4954[高清版].mp4    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-5670[高清版].mp4    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-6294[超清版].flv    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-6821[高清版].mp4    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-7588[高清版].mp4    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-8043[超清版].flv    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-8529[高清版].mp4    OK
D:\bilibili\0001.哔哩哔哩-那年那兔那些事儿 第二季-9061[高清版].mp4    OK
D:\bilibili\【历史_战争】鸦片战争 1997年【CCTV6高清720p】[高清版]\合并\0001.哔哩哔哩-【历史_战争】鸦片战争 1997年【CCTV6高清720p】[高清版].flv    OK
D:\bilibili\鸦片战争前夕的世界_flv-国语高清.qsv  OK
# ----------------------------------------------------------------
# 扫描文件个数: 13
# 扫描文件夹个数: 3
# 感染文件个数: 0
# 扫描文件的总大小: 2897597658
# 病毒数据库: 170914-2, 17/09/14
# 扫描时间总计: 0:0:1

比卡巴斯基的优势是扫描速度更快,而且完美的支持中文。但是需要在扫描结束之后同步读取刚刚生成的日志文件,对系统开销会更大。另外卡巴斯基其实也支持生成日志文件。

卡巴斯基+NodeJS打造远程杀毒服务器相关推荐

  1. 机房管理系列之杀毒服务器维护

    对于企业安全管理方面,"防患于未然",事前的预防远远大于事故处理,在企业内部保障机房服务器安全运行尤为重要,如何确保企业的安全?我们接下来讲的就是对Symantec杀毒服务器的管理 ...

  2. 手动打造优盘杀毒伴侣

    手动打造优盘杀毒伴侣 手动打造优盘杀毒伴侣 前两天,一木的计算机突然中了病毒,系统出现问题,进不了桌面,更别说用杀毒软件杀毒.回忆起当年有软驱的时代还真是方便,只要进入DOS,用软盘杀毒即可解决问题. ...

  3. clamav 远程杀毒服务安装

    背景知识: clamav 作为开源的杀毒程序,可以直接对本地文件进行定期杀毒扫描,也可以启动杀毒服务,由远程程序调用服务将文件传输过来,扫描后返回是否为病毒的状态,可用于业务系统中文件上传后调起远程扫 ...

  4. w10取消自带杀毒服务器,win10家庭版关闭杀毒服务如何设置_win10家庭版怎么关闭自带杀毒系统-win7之家...

    在 具体方法: 1.使用快捷键(WIN+R)调出运行工具,然后再输入组策略命令(regedit)再点击确定,打开注册表. 2.打开注册表,找到HKEY_LOCAL_MACHINE\SYSTEM\Cur ...

  5. [原创]万能杀毒,打造手工杀毒高手

    娘西皮的,好久没写文章了,实在懒的动了,今天介绍下手工杀毒,很早俺就在群里简单的说过一下,今天来个详细滴 首先,前提是你的系统分区是NTFS,如果不是,唉,大叔,你已经落后很多了,赶紧换吧(crack ...

  6. w10取消自带杀毒服务器,如何关闭win10自带杀毒软件 Windows Defender 看完你就知道了...

    很多小伙伴的电脑一般都会安装第三方杀毒软件,不过Win10系统还自带了Windows Defender杀毒软件,但有时候会明显占用系统资源,容易引起系统卡顿.那怎样关闭呢,接下来由我为大家介绍一下. ...

  7. squid+icap+clamav网关杀毒

    squid+icap+clamav网关杀毒 作者:张惠(jimzhang) QQ号:872656885 E-mail.msn:zhanghui8059@126.com 个人blog:zhanghui8 ...

  8. 「杀毒」卡巴斯基 5.0.388 单机简体中文专业版

    Kaspersky(卡巴斯基)杀毒软件来源于俄罗斯,是世界上最优秀.最顶级的网络杀毒软件,查杀病毒性能远高于同类产品.Kaspersky(卡巴斯基)杀毒软件具有超强的中心管理和杀毒能力,能真正实现带毒 ...

  9. 服务器杀毒软件推荐--服务器安全狗2合1杀毒版来啦

    2019独角兽企业重金招聘Python工程师标准>>> 服务器安全狗是国内首款支持windows全系列操作系统(Windows2003/Windows2008/Windows2012 ...

最新文章

  1. 虚拟机linux 8.04汉化,在虚拟机中快速安装 Ubuntu 18.04
  2. Python学习之==json处理
  3. 【数据结构与算法】之深入解析“排列硬币”的求解思路与算法示例
  4. ueditor 编辑html文件名,UEditor编辑器自定义上传图片或文件路径的修改方法,ueditor修改方法...
  5. leetcode27 移除元素
  6. 《天天数学》连载09:一月九日
  7. onu光功率多少是正常_电信宽带升级为200M光纤,为什么网速没有提升多少?
  8. linux下抓包工具 wireshark,网络抓包工具Wireshark的简单使用
  9. MarkDown 的两种页内跳转方法!!!!!
  10. soapUI接口测试工具所有版本下载地址
  11. 使用google翻译api
  12. SQL中常用的日期函数
  13. 中国生物医药产业集群产业战略布局及运营管理模式分析报告2021-2027年
  14. 得实打印机断针测试软件原理,得实针式打印机断针测试软件
  15. Epicor 客制化 - 常用对象
  16. Go:一次 exit code 是 137 且 无 coredump 的排错经历
  17. maven 系列 06 - 向本地仓库导入jar包 (例如 - pinyin4j-2.5.0)
  18. AIM Tech Round (Div. 1) C. Electric Charges 二分
  19. 用matlab绘制分段函数曲线
  20. houdini节点大全中文手册_【技术贴】武林秘籍在此!大咖座谈虚幻引擎制作影视动画经验!...

热门文章

  1. WebRTC基础实践 - 5.通过RTCPeerConnection传输流媒体视频
  2. 學習雜記(SpringCloud)
  3. 2022 APMCM亚太数学建模竞赛 C题 全球是否变暖 问题一python代码实现(更新完毕)
  4. 互联网金融开发软件公司值得选择的有哪些?
  5. python扫雷 高级算法_利用Python实现自动扫雷
  6. 联想昭阳E47A无线网卡指示灯不亮,搜不到无线信号,解决办法
  7. java 双向链表排序_数据结构之(2)JAVA实现双向链表
  8. 计算机网络与分布式系统的区别
  9. 黑盒测试比白盒测试技术要求更高吗?
  10. 【数据产品案例】阿里生意参谋-竞争情报