注意:下面的步骤都是要基于服务端&客户端已经能实现内网穿透,如果没有,请移步:Linux环境搭建frp实现内网穿透
准备工作:
使用electron-vue框架,跑起来项目, 参考地址: https://simulatedgreg.gitbooks.io/electron-vue/content/cn/ 跑起来长这样
服务端&客户端已经能实现内网穿透,参考文章:http://lvsige.top/archives/19
如果以上两项都完成了,那么请继续~
捋一下思路
一个穿透软件,需要具备的能力:用户安装软件后,只需要填写本地端口号以及期望的域名,点击连接,即可使用域名访问本地文件。
- 服务端是不用管的,已经配置ok
- 客户端需要把解压后的frp文件夹,让用户能随心修改。(不能说每个用户使用此软件时,都需要在本地下载一个frp压缩包)
- 能够在软件里启动子进程。
./frpc -c ./frpc.ini
这个命令应该自动完成。
实现方法
需要读写frp/frpc.ini文件里的内容
用到nodejs里的ini, fs, path
模块。
需要启动frp
用nodejs里 child_process
模块。child_process文档
具体代码
把解压后的frp文件夹放在electron-vue项目里
在主进程里:
代码语言:javascript复制const ini = require('ini')
const path = require('path')
const fs = require('fs')
let appPath = path.resolve(__dirname, '../../')
let filePath = path.join(appPath, 'frp', 'frpc.ini')
let config = null
// 开始读取数据
fs.readFile(filePath, (err, data) => {
if (data) {
config = ini.parse(data.toString())
app.config = config
}
})
点击"连接"时, 能够修改frpc.ini
代码语言:javascript复制// 写入数据
function writeConfig(config) {
var iniObj = {
common: {
server_addr: 'x.x.x.x',
server_port: 7000,
},
web: {
type: 'http',
local_port: config.port,
custom_domains: `${config.hostname}${config.thost || '.lvsige.top'}`,
},
}
let iniStr = ini.encode(iniObj)
fs.writeFileSync(filePath, iniStr)
}
可以读取写入frpc.ini之后, 就要建立连接了
nodejs里的子进程模块 http://nodejs.cn/api/child_process.html
代码语言:javascript复制const exec = require('child_process').exec
ipcMain.on('connectEvent', (event, arg) => {
writeConfig(arg)
zlog.info('接收到参数 开始建立连接')
let filePath = path.join(appPath, 'frp')
workerProcess = exec(
`cd ${filePath}
chmod 755 *
./frpc -c ./frpc.ini
`,
{}
)
// 给当前目录所有文件修改权限为755
// 打印正常的后台可执行程序输出
workerProcess.stdout.on('data', (data) => {
event.sender.send('okAllInfo', data)
zlog.info(data, '打印正常的后台可执行程序输出')
})
// 打印错误的后台可执行程序输出
workerProcess.stderr.on('data', (data) => {
zlog.info(data, '打印错误的后台可执行程序输出')
})
// 退出之后的输出
workerProcess.on('exit', (code) => {
zlog.info('process exit', code)
})
})
关闭断开连接时
代码语言:javascript复制// 退出
ipcMain.on('close', (event, arg) => {
zlog.info('断开连接, 收到信号了')
exec('ps -ef|grep frp', function (err, stdout, stderr) {
stdout.split('n').filter(function (line) {
var p = line.trim().split(/s /)
var address = p[1]
if (
address !== undefined &&
address !== 'PID' &&
p.some((item) => {
return item === './frpc.ini'
})
) {
exec('kill ' address, function (err, stdout, stderr) {
if (err) {
return zlog.info('杀死进程失败!!')
}
event.sender.send('killProcess')
zlog.info('杀死进程成功')
})
}
})
})
})