Nodejs-ajax跨域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const http=require('http');

let allowOrigin={
'http://localhost': true,
'http://aaa.com': true,
'https://aaa.com': true,
}

http.createServer((req, res)=>{
let {origin}=req.headers;

if(allowOrigin[origin]){
res.setHeader('access-control-allow-origin', '*');
}

res.write('{"a": 12, "b": "Blue"}');
res.end();
}).listen(8080);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script>
window.onload=function (){
let oBtn=document.getElementById('btn1');

oBtn.onclick=function (){
let ajax=new XMLHttpRequest();

ajax.open('GET', 'http://localhost:8080/a', true);
ajax.send();

ajax.onreadystatechange=function (){
// readyState 0~4
// 0:初始化 1:已连接 2:已发送 3:响应头已经接收到 4:相应体已经接受
if(ajax.readyState==4){
if(ajax.status>=200 && ajax.status<300 || ajax.status==304){
alert('成功');
let json=JSON.parse(ajax.responseText);
console.log(json);
}else{
alert('失败');
}
}
};
};
};
</script>
</head>
<body>
<input type="button" value="请求" id="btn1">
</body>
</html>

ajax为什么不能跨域?

SOP:同源策略,你代码请求的资源应该和你在一个域名下,如果不是,浏览器会禁止这个请求。

ajax是被谁阻止住的?

不是服务器,是浏览器阻止的,这是浏览器的一种”自律”的行为。

服务器是一定会响应的,响应后如果不是同源,浏览器会把这个东西扔掉。

所以这个时候需要服务器返回数据的时候需要声明一下,声明我们是一家子(就是声明哪些人可以从我这里获取数据),如上代码。



Nodejs-几个系统包

assert

1
2
3
4
assert(5<3, 'aaa');

assert.deepEqual(变量, 预期值, msg); // 深度比较,相当于 ==
assert.deepStrictEqual(变量, 预期值, msg); // 相当于 === (比较类型)

path

1
2
3
4
5
6
7
8
9
10
11
const path=require('path');

let str='/root/a/b/1.txt';

console.log(path.dirname(str)); // 文件夹名 /root/a/b
console.log(path.extname(str)); // 扩展名 .txt
console.log(path.basename(str)); // 文件名 1.txt

console.log(path.resolve('/root/a/b', '../c', 'build', '..', 'strict'));
console.log(path.resolve(__dirname, 'build'));
// __dirname 类似于C中的宏,是当前路径

url

1
2
3
4
const url=require('url');

let str='http://www.bing.com:8080/a/b/1.html?a=1&a=2&a=3';
console.log(url.parse(str, true)); // true表示解析后面的参数(query),解析成 JSON,不加true就是一个字符串

querystring

1
2
3
4
const querystring=require('querystring');

console.log(querystring.parse("a=12&b=5&c=99"));
console.log(querystring.stringify({a: 12, b: 99, c: 'blue'}));

net

网络通信。

OSI七层参考模型
物理层 > 数据链路层 > 网络层(IP) > 传输层(TCP) > 会话层 > 表现层 > 应用层(HTTP)

5层模型
物理层 > 数据链路层 > 网络层(IP) > 传输层(TCP) > 应用层(HTTP)

net就是传输层(TCP)的一个包,可以保证质量。


TCP:保证质量,特别适合网络传输文件,不能丢数据。

UDP:保证速度,特别适合网络视频直播等,丢一两帧问题不大。



Nodejs-处理POST文件数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
用户:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="file" name="f1">
<input type="submit" value="提交">
</form>
</body>
</html>

Nodejs中原生不带处理文件数据的包。

POST 文件:

原生处理

1
2
POST文件
<分隔符>\r\n字段信息\r\n\r\n内容\r\n<分隔符>\r\n字段头\r\n\r\n内容\r\n<分隔符>\r\n字段头\r\n\r\n内容\r\n<分隔符>--
  1. 用<分隔符>切分
1
2
3
4
5
6
7
[
null,
"\r\n字段信息\r\n\r\n内容\r\n",
"\r\n字段信息\r\n\r\n内容\r\n",
"\r\n字段信息\r\n\r\n内容\r\n",
'--'
]
  1. 第0个和最后1个,扔掉
1
2
3
4
5
[
"\r\n字段信息\r\n\r\n内容\r\n",
"\r\n字段信息\r\n\r\n内容\r\n",
"\r\n字段信息\r\n\r\n内容\r\n",
]
  1. 每一项
1
2
3
4
"\r\n字段信息\r\n\r\n内容\r\n"

"字段信息\r\n\r\n内容"
"字段信息", "内容"

multiparty 包

安装

npm i multiparty -D

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const http=require('http');
const multiparty=require('multiparty');

http.createServer((req, res)=>{
let form=new multiparty.Form({
uploadDir: './upload' // 上传到哪里
});

form.parse(req);

form.on('field', (name, value)=>{
console.log('字段:', name, value);
});
form.on('file', (name, file)=>{
console.log('文件:', name, file);
});

form.on('close', ()=>{
console.log('表单解析完成');
});
}).listen(8080);

上传的文件名是随机的,重名概率不大(特别小),万一重复就会覆盖之前的文件。



【Nao机器人】机器人校准

正确校准的机器人非常重要,因为软件要求NAO的所有部件都在预期的位置。否则,NAO将无法稳定行走,从图像坐标投影到世界坐标(反之亦然)将是错误的。
一般来说,很多计算都是不可靠的。NAO的两个物理组件可以通过SimRobot进行校准,关节和摄像机。经常检查这些校准是很重要的,特别是对关节来说。
随着时间的推移和使用,关节会磨损。尤其是髋关节。除此之外,B-Human软件还使用四种颜色类(官方文档4.1.4节),这些颜色类也需要校准。改变位置或光照条件可能需要对其进行调整。

阅读更多
【Nao机器人】ssh使用Nao

有几个脚本可以通过SSH启动和停止NAOqi和bhuman。这些脚本在安装B-Human软件时被复制到NAO。

阅读更多
【Nao机器人】BHuman的组件和配置

B-Human 软件是跨平台的, 包含两个用于 NAOqi 的实际机器人共享库,一个用于机器人的附加可执行文件,相同的运行在模拟器SimRobot(没有 NAOqi)的软件,以及一些库和工具,因此,该软件分为以下组件。

阅读更多
【Nao机器人】刷机

给 Nao (小宝贝) 部署 Naoqi 系统和 BHuman 系统。

阅读更多
【Nao机器人】BHuman中的Config

本文主要记录了 BHuman 代码中的 Config 目录的一些东西。

2016 的代码和 2017/2018 的代码在 Config 上面稍微有些不同。由于代码的重新编译在某些情况下需要花费大量的时间,并且每个机器人需要不同的配置,软件使用了大量的配置文件,这些文件可以在不引起重新编译的情况下进行修改。

软件使用的所有文件都位于 Config 目录下。还有一些机器人操作系统的配置文件,它们位于Install目录中。

阅读更多
Nodejs-基础结构和数据处理

同步、异步

在 node.js 中绝大多数的异步操作。

HTTP 协议

规定了浏览器和服务器之间如何进行交互。

HTTP 发展过程

1
2
3
4
HTTP 1.0 RFC-1945
HTTP 1.1 RFC-2616 持久连接(连接完了一定时间内不会马上断开)
HTTPS RFC-2818 安全协议
HTTP 2.0 RFC-7540 加密、头部压缩、服务器推送、管线操作、多路复用

HTTP 报文结构

1
2
header <= 32K
body <= 2G

HTTP 状态码

1
2
3
4
5
1xx 信息
2xx 成功
3xx 重定向(你需要的资源不在我这,在另外一个地址,你去找他要)
4xx 请求错误(404 not found,是请求错误)
5xx 服务器错误(是服务器的错误,不是你的错)

HTTP 请求方式

1
2
3
4
5
6
GET   获取
数据放在url里面传输的
1.容量小<=32K

POST 发送数据
1.容量大

http 模块

1
2
3
4
5
6
7
const http=require('http');

let server=http.createServer(function (req, res){ // request(请求), response(相应)
res.write('abc');
res.end(); // 发完东西结束请求,告诉浏览器不用等了,我发完了。
});
server.listen(8080);

fs 模块

file system。

fs.writeFile(path, data, callback);fs.readFile(path, callback);他俩就是异步操作,当然他俩也有同步的版本:fs.writeFileSyncfs.readFileSync

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const fs=require('fs');

//fs.writeFile(path, data, callback);
//fs.readFile(path, callback);

// 写入文件
fs.writeFile('./a.txt', 'asdfasdfad', err=>{
if(err){
console.log('失败', err);
}else{
console.log('成功')
}
});
// 读取文件
fs.readFile('./a.txt', (err, data)=>{ // 返回的是一个 Buffer 数据(原始的二进制数据)
if(err){
console.log('错误', err);
}else{
console.log('成功', data);
}
});

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const http=require('http');
const fs=require('fs');

let server=http.createServer(function (req, res){
console.log(req.url);
//req.url =>'/1.html'
//=>'www/1.html'

fs.readFile(`www${req.url}`, (err, buffer)=>{ // 读取相应的文件
if(err){ // 如果请求错误
res.writeHeader(404); // 状态码
res.write('Not Found'); // 显示
res.end(); // 结束
}else{
// res.writeHeader(200); // 200 代表成功,默认是这个
res.write(buffer);
res.end();
}
});
});
server.listen(8080);

GET 请求

一次给到数据库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form action="http://localhost:8080/aaa" method="get">
用户:<input type="text" name="username" /><br>
密码:<input type="password" name="password" /><br>
<input type="submit" value="提交" />
</form>
</body>
</html>

querystring 模块

1
2
3
4
5
6
7
8
9
10
const http=require('http');
const querystring=require('querystring');

let server=http.createServer(function (req, res){
let [url, query]=req.url.split('?');
let get=querystring.parse(query);

console.log(url, get);
});
server.listen(8080);

url 模块

1
2
3
4
5
6
7
8
9
const http=require('http');
const url=require('url');

let server=http.createServer(function (req, res){
let {pathname, query}=url.parse(req.url, true); // true 就是告诉他连 query 一块处理了吧,处理完变成一个 JSON

console.log(pathname, query);
});
server.listen(8080);

POST 请求

POST 因为比较大,可能会分几次发给服务器。接收的时候也要分段来接收。

req.on事件、req.end事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const http=require('http');
const querystring=require('querystring');

let server=http.createServer(function (req, res){
let arr=[];
req.on('data', buffer=>{
arr.push(buffer);
});

req.on('end', ()=>{
let buffer=Buffer.concat(arr); // 将 arr 中的数据拼在一起
let post=querystring.parse(buffer.toString()); // 转为字符串
console.log(post);
});
});
server.listen(8080);

同时接收 GET 和 POST 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const http=require('http');
const url=require('url');
const querystring=require('querystring');
const fs=require('fs');

http.createServer((req, res)=>{
let path='', get={}, post={};

if(req.method=='GET'){ // 如果是 GET 方式
let {pathname, query}=url.parse(req.url, true);
path=pathname;
get=query;
complete();
}else if(req.method=='POST'){ // 如果是 POST 方式
path=req.url;
let arr=[];

req.on('data', buffer=>{
arr.push(buffer);
});

req.on('end', ()=>{
let buffer=Buffer.concat(arr);
post=querystring.parse(buffer.toString());
complete();
});
}

function complete(){
console.log(path, get, post);
}
}).listen(8080);

接口

接口-API:用户注册、登录

服务器:

  1. 请求文件 -> 结果
  2. 请求接口 -> 操作
1
2
3
4
5
6
7
注册接口:
/reg?username=xxx&password=xxx
=>{error: 1, msg: '为什么'}

登录接口:
/login?username=xxx&password=xxx
=>{error: 1, msg: 'xx'}

用户注册登录案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script src="jquery.js" charset="utf-8"></script>
<script>
$(function (){
$('#btn1').click(()=>{
$.ajax({
url: '/reg',
data: {
username: $('#user').val(),
password: $('#pass').val()
},
dataType: 'json'
}).then(json=>{
if(json.error){
alert(json.msg);
}else{
alert('注册成功');
}
}, err=>{
alert('注册失败,请刷新重试');
});
});

$('#btn2').click(()=>{
$.ajax({
url: '/login',
data: {
username: $('#user').val(),
password: $('#pass').val()
},
dataType: 'json'
}).then(json=>{
if(json.error){
alert(json.msg);
}else{
alert('登录成功');
}
}, err=>{
alert('登录失败,请刷新重试');
});
});
});
</script>
</head>
<body>
用户:<input type="text" id="user" /><br>
密码:<input type="password" id="pass" /><br>
<input type="button" value="注册" id="btn1">
<input type="button" value="登录" id="btn2">
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
const http=require('http');
const url=require('url');
const querystring=require('querystring');
const fs=require('fs');

let users={};

http.createServer((req, res)=>{
let path='', get={}, post={};

if(req.method=='GET'){
let {pathname, query}=url.parse(req.url, true);

path=pathname;
get=query;
complete();
}else if(req.method=='POST'){
path=req.url;
let arr=[];
req.on('data', buffer=>{
arr.push(buffer);
});

req.on('end', ()=>{
let buffer=Buffer.concat(arr);
post=querystring.parse(buffer.toString());
complete();
});
}

function complete(){
if(path=='/reg'){
let {username, password}=get;

if(users[username]){
res.write(JSON.stringify({error: 1, msg: '此用户名已存在'}));
res.end();
}else{
users[username]=password;

res.write(JSON.stringify({error: 0, msg: ''}));
res.end();
}
}else if(path=='/login'){
let {username, password}=get;

if(!users[username]){
res.write(JSON.stringify({error: 1, msg: '找不到此用户'}));
res.end();
}else if(users[username]!=password){
res.write(JSON.stringify({error: 1, msg: '密码不对'}));
res.end();
}else{
res.write(JSON.stringify({error: 0, msg: ''}));
res.end();
}
}else{
fs.readFile(`www${path}`, (err, buffer)=>{
if(err){
res.writeHeader(404);
res.write('Not Found');
res.end();
}else{
res.write(buffer);
res.end();
}
});
}
}
}).listen(8080);


Nodejs-入门

node 一般是作为 前端和服务器中间的中间层,比如做一些数据处理,数据缓存等,减少服务器压力,也可以处理一些不安全的东西。

用途:

  1. 中间层(安全性、性能、降低主服务器复杂度)
  2. 小型服务
  3. 工具

优势:

  1. 性能高
  2. 利于和前端代码整合
阅读更多