服务器网页版上位机设计 01 服务器
本设计主要涉及三个方面: 服务器,网页版,上位机.
起因是我实习时的第一个项目,为本地的qt上位机编写个网页版.已经完成较久了,现在来总结一下.
首先是第一篇:关于服务器的搭建.
1.安装 nodejs
推荐参考: << Node.js最新最详细安装教程(2020)_蜡笔小柯南的博客-CSDN博客_node >>
-
下载安装包: << 下载 | Node.js 中文网 (nodejs.cn) >>
-
打开安装包,下一步点到底,默认安装所有东西.除了中途有个打勾,默认没有选上,也不用选,翻译的意思是"自动安装工具".记得更改安装目录.
-
重新打开终端,输入指令查看是否安装完成:
node -v // 显示安装的 nodejs 版本
npm -v // 显示安装的 npm 版本
- 修改全局模块路径和缓存路径;设置路径时,别忘记加双引号;设置完后查看验证.
npm config set prefix "创建的 node_global 文件夹所在路径"
npm config set cache "创建的 node_cache 文件夹所在路径"
// 查看验证
npm config get prefix
npm config get cache
- 添加 系统变量
NODE_PATH
,值为node_global
文件夹的路径;(添加在用户变量中也可以) - 修改 系统变量
Path
,添加nodejs
安装路径,用于终端使用node
指令.(添加在用户变量中也可以)
吐槽一句,win11的修改方法,在系统中搜索
环境变量
,有一个"…系统…“,有一个”…账户…",后者打开的窗口是不能修改系统变量的.也可以不搜索,一步步打开,打开的是前者: << windows 11 设置环境变量_邓什么峰的博客-CSDN博客_win11环境变量 >>
1.1创建工程目录
- 推荐
IDE
是VS Code
, 如果使用纯文本,推荐notepad++
, (学术研究无国界无瓜)
https
: 存放 https 密钥等文件;Markdown
: 存放 笔记,也就是文档内容;node_modules
: 存放 工程所依赖的 node 模块包;static/css
: 存放 网页样式;static/image
: 存放 网页图片;static/js
: 存放 网页脚步;template
: 存放 网页本体;WEB_SERIA_API
: 存放 以上所有内容,父级目录,工程目录.即 :./
;
2.安装 express
推荐参考: << Node.js Express 框架 | 菜鸟教程 (runoob.com) >>
- 使用 node 的 npm 工具 安装, 在工程目录下打开终端输入指令:
npm install express --save
- 在工程目录
./
下,创建服务器脚本,server.js
;
// 一个简洁而灵活的 node.js Web应用框架
const express = require('express');
const app = express();
// 访问本地静态文件, __dirname 代表本脚本的路径
app.use('/', express.static(__dirname));
// 启动 http 服务器端
const httpServer = app.listen(8081, function ()
{
let host1 = "192.168.1.10" // 本机 IPv4 地址
let host2 = "127.0.0.1" // 本机 地址
let host3 = "localhost" // 本地 服务器
let port = httpServer.address().port
// 这里只是在终端输出打印字符
console.log("应用实例,访问地址为 http://%s:%s/template/1.html", host1, port)
console.log("应用实例,访问地址为 http://%s:%s/template/1.html", host2, port)
console.log("应用实例,访问地址为 http://%s:%s/template/1.html", host3, port)
})
- 以上代码参考菜鸟教程中的示例. 其中
app.use()
有多种用法,这里使用其中一种,其效果是授权/允许通过网页访问哪些本地内容.这里允许访问整个工程.
app.use()
参考 << Express中app.use()用法 - 简书 (jianshu.com) >>,
- 在工程目录
./template
下, 创建网页,1.html
;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>
</body>
</html>
- 以上代码拷贝菜鸟教程中的示例.现在,启动
server.js
脚本,然后点击网址,就可以访问网页了.
2.1 不同的 host
推荐参考: << localhost与127.0.0.1的区别_席飞剑的博客-CSDN博客_localhost和127.0.0.1的区别 >>
- 你或许已经发现,
server.js
脚本中,host
设置了3个值,你使用哪个值访问都是可以打开网页的.如果只是访问网页,暂时没啥区别,不过如果要用到本项目的核心:Web Serial API
,那就有个大问题了. - 可以用3个网址打开网页,然后打开开发者控制台(一般快捷键
F12
),然后输入js代码:
("serial" in navigator) // 这行代码用于判断当前环境是否能使用 Web Serial API
- 会发现使用
IPv4
地址时,返回的是false
.这代表这个项目最终只能本地访问,不能被其他设备访问.这是个大问题.
我项目开展到最后局域网测试时才发现这个问题,困惑了很久.最后无奈请示老板.老板介绍了一个其他公司的技术人员给我.最后发现,原来是
Web Serial API
,只支持在https
协议下或本地浏览器.因为不懂https和http的区别,只知道前者更加保密安全.
-
其实在官方手册上,最开头上面的就是一句: “Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.” 翻译: “安全上下文:此功能仅在安全上下文 (HTTPS)、部分或所有支持的浏览器中可用。”
-
express
创建的默认是http
的,如果直接输入https://
访问会失败.
3.创建 https
推荐参考: << node配置本地https服务_菜鸟驿站2020的博客-CSDN博客_node 本地https >>
- 安装
openssl
, << Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions (slproweb.com) >>,往下拉可以看到下载,有多个版本选择.(我也不知道有什么不同,选了个看似比较正常的)
- 下载安装完成后,设置 系统变量
Path
,添加安装路径下的bin
文件夹路径,这样才能在终端使用指令下图中,倒数第一个就是了,倒数第二个是第一节中添加的,这里一起展示.添加后就可以在终端输入openssl
测试是否有效.
- 在工程目录
./https
下,打开终端,以此输入以下指令:
// 在当前目录生成 privatekey.pem 文件
openssl genrsa -out privatekey.pem 1024
// 在当前目录生成 certrequest.csr 文件 ; 第一个输入 cn ,后续全回车跳过
openssl req -new -key privatekey.pem -out certrequest.csr
// 在当前目录生成 certificate.pem 文件
openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
- 在脚本
./server.js
后面 直接 添加 如下代码:
// 启动 https 服务需要 https 包
// 读取文件需要 fs 包
const https = require('https');
const fs = require('fs');
// 将两个证书文件读取放到 options 对象中
// 使用 readFileSync() 方法,顺序地执行 读文件 和 启动服务 操作
const options =
{
key: fs.readFileSync('./https/privatekey.pem'), //密钥路径
cert: fs.readFileSync('./https/certificate.pem')
};
// 创建服务器,使用 express 框架
const httpsServer = https.createServer(options, app)
// 启动 https 服务器,设置监听端口号
httpsServer.listen(8080, function ()
{
let host = "192.168.1.10" // 本机 IPv4 地址
let port = httpsServer.address().port
console.log("应用实例,访问地址为 https://%s:%s/template/1.html", host, port)
})
- 再次重新启动脚本,访问网址,会提示不安全访问,因为自己创建的
https
密钥没有认证,没关系,点击继续访问即可.这时再打开浏览器的开发者控制台,输入指令判断是否能使用Web Serial API
,得到True
.
4.get 与 post 请求
推荐参考: << Express全系列教程之(四):获取Post参数的两种方式_蓝袍小将的博客-CSDN博客_express获取post数据 >>
<< Express全系列教程之(三):获取get参数_蓝袍小将的博客-CSDN博客_express获取get参数 >>
- 替换网页代码
./template/1.html
,测试 get 与 post 请求,参考上面帖子中的示例 :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- 注意,这里填 https 或 http 都可以,
不过使用 http 会有个提示不安全,但仍可发送,
记得修改端口号,二者使用的端口号不一样. -->
<form action="https://192.168.1.10:8080/express_post" method="post" enctype="application/x-www-form-urlencoded">
用户:
<input type="text" name="user" id="user" placeholder="用户名"><br>
密码:
<input type="password" name="password" id="password" placeholder="密码"/><br>
<input type="submit" value="提交"/>
</form>
</body>
</html>
- 使用 node 的 npm 工具 安装, 在工程目录下打开终端输入指令:
npm install body-parser --save
- 在脚本
./server.js
后面 直接 添加 如下代码,参考上面帖子中的示例 :
// express 处理 get 请求
app.get('/express_get', function (req, res)
{
let data= req.query // 取出参数,字典的形式
console.log(data) // 在中断打印接收到参数
res.send(data) // 页面输出接收到的参数
})
// express 处理 post 请求
// Express 中默认都使用 body-parser 作为请求体解析 post 数据
const bodyParser = require("body-parser");
// 解析以 application/json 和 application/x-www-form-urlencoded 提交的数据
const jsonParser = bodyParser.json();
const urlencodedParser = bodyParser.urlencoded({ extended: false });
// 全局作用
app.use(jsonParser);
app.use(urlencodedParser);
// req 代表请求对象 res 代表返回对象
app.post('/express_post', function(req,res)
{
// req: 客户端 携带的信息
console.log(
[req.query, // 打印 get 参数
req.params, // 打印 不知道什么
req.body, // 打印 post 数据
req.get('Origin'), // 打印 网址:端口
req.url]); // 打印 端口后面的
res.send(req.body); // 返回 get 参数
});
4.1 get 请求
- 直接访问网址,就是发出
get
请求.然后?
后面附带参数,不同参数使用&
分割.
https://192.168.1.10:8080/express_get?1=1&2=2&1=2
- 参数是字典的形式,
=
左边就是键名,右边就是键值,二者都是字符型,如果有重复的键名会归为一类,用列表表示.
{"1":["1","2"],"2":"2"}
4.2 post 请求
post
请求的发出需要有脚本,所以将网页内加入表单,用于测试.- 注意: 脚本中使用了
app.use()
;避免在app.post()
中每次写多一个参数;
app.post('/express_post', bodyParser.json(), function(req,res)
{...});
- 其他更多关于
post
请求的用法,在网页脚步中讲解.
5.总结
- 总体看下来没多少东西,不到半小时就能复制粘贴完了,自己摸索的时候花了一天.因为很多东西都是第一次接触,连概念都没有.
- 本文讲了服务器的建立了,下一篇,讲网页的制作,再下一篇讲上位机的代码.完结.