什么是 Web
服务器?
HTTP
请求获取到这个资源Web
服务器目前有很多开源的 Web
服务器:Nginx
、Apache(静态)
、Apache Tomcat(静态、动态)
、Node.js
在 Node
中,提供 web
服务器的资源返回给浏览器,主要是通过 http
模块。
我们先简单对它做一个使用:
jsconst http = require("http");
const HTTP_PORT = 9000;
const server = http.createServer((req, res) => {
res.end("Hello World");
});
server.listen(HTTP_PORT, () => {
console.log(`服务器在${HTTP_PORT}启动`);
});
此时我们在浏览器中输入 localhost:9000
,就会出现 Hello World
:
解释上面这段代码:
通过 http
模块的 createServer
方法创建了一个服务器对象,它的底层其实是直接使用 new Server
创建对象的。
那么当然,我们也可以自己来创建这个对象:
jsconst server = new http.Server((req, res) => {
res.end("Hello World");
});
server.listen(HTTP_PORT, () => {
console.log(`服务器在${HTTP_PORT}启动`);
});
创建 Server
时会传入一个回调函数,这个回调函数在被调用时会传入两个参数:
req
:request
请求对象,包含请求相关的信息;res
:response
响应对象,包含我们要发送给客户端的信息;Server
通过 listen
方法来开启服务器,并且在某一个主机的端口上监听网络请求
也就是当我们通过 ip:port
的方式发送到我们监听的 Web
服务器上时,我们就可以对其进行相关的处理;
listen
函数有三个参数:
端口 port
:可以不传,系统会默认分配端
主机 host
:通常可以传入 localhost
、ip地址127.0.0.1
、或者 ip地址0.0.0.0
,默认是 0.0.0.0
;
localhost
:本质上是一个域名,通常情况下会被解析成 127.0.0.1
;
127.0.0.1
:回环地址(Loop Back Address)
,表达的意思其实是我们主机自己发出去的包,直接被自己接收;
127.0.0.1
时,在同一个网段下的主机中,通过 ip地址
是不能访问的;0.0.0.0
:
IPV4
上所有的地址,再根据端口找到不同的应用程序;0.0.0.0
时,在同一个网段下的主机中,通过 ip
地址是可以访问的;回调函数:服务器启动成功时的回调函数;
我们会发现,对于前端开发来说,通常很少会和二进制直接打交道,但是对于服务器端为了做很多的功能,我们必须直接去操作其二进制的数据;
所以 Node
为了可以方便开发者完成更多功能,提供给了我们一个 Buffer
类用来创建一个专门存放二进制数据的缓存区,并且它是全局的。
我们可以将 Buffer
看成是一个存储二进制的数组,这个数组中的每一项,可以保存 8
位二进制:0000 0000
Buffer
相当于是一个字节的数组,数组中的每一项对应一个字节的大小:
如果我们希望将一个字符串放入到 Buffer
中,是怎么样的过程呢?
jsconst buffer = new Buffer("hello");
console.log(buffer);
打印结果如下:
可以看到打印出的 Buffer
对象包含了五个 由两位十六进制组成的数字。而我们知道 2
位十六进制正好对应 8
位二进制也就是一个字节
而如果你去查询 ASCII
表的话会发现,这五个十六进制数正好对应着英文字母的 h
e
l
l
o
也就是说,我们可以得出结论:Buffer
存储字符串时默认是以 ASCII
将字符串编码存储的
Buffer
默认是以 utf-8
为默认编码存储中文的
在上面一小节的例子中,我们使用 new Buffer()
创建了一个 Buffer
对象,事实上由于安全性和可用性的问题,Node
已经废弃了这种方法,推荐使用 Buffer.alloc()
、Buffer.allocUnsafe()
或者 Buffer.from()
这三种方法创建 Buffer
对象
接下来我们试着用 Buffer
存储中文:
jsconst buf = Buffer.from("你好");
console.log(buf);
打印结果如下:
我们知道在 UTF-8
中,一个中文等于三个字节。而在上面的打印结果也能看出 “你好”
两个字正好存储了六个两位十六进制的数字,证实了我们的结论。
乱码的问题:
Buffer.from()
方法中,我们还可以添加第二个参数来规定使用哪种编码方式jsconst fs = require("fs");
const buf = Buffer.from("你好", "utf16le");
console.log(buf.toString("utf16le"));
console.log(buf.toString("utf8"));
打印结果:
可以看到,同时以 utf-16
解码打印出来没有出现乱码,而以 utf-8
解码打印出来出现了乱码。
关于 Buffer
的创建方式还有很多,见下图
这里主要再讲一下 alloc
,如果有学习 c
语言的应该是很熟悉的。它的意思是 承认、同意。Buffer.alloc
的作用为向内存申请一个多长的 Buffer
,里面的默认数据是 00
。
jsconst buf = Buffer.alloc(8);
console.log(buf);
打印结果如下
我们也可以对其进行操作
jsbuf[0] = "w".charCodeAt();
buf[1] = 100;
buf[2] = 0x66;
console.log(buf); // <Buffer 77 64 66 00 00 00 00 00>
console.log(buf[0]); // 119
console.log(buf[2].toString()); // 102
在上一章 fs
模块中介绍中,我们提到了 readFile
的回调是一个 Buffer
,现在大家应该也能理解了吧
jsconst fs = require("fs");
fs.readFile("./test.txt", (err, data) => {
console.log(data); // <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>
console.log(data.toString()); // Hello World
});
jsconst fs = require("fs");
fs.readFile("./image.png", (err, data) => {
console.log(data); // <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 ... 1878012 more bytes>
});
对于任何一个为服务端服务的语言或者框架来说,通常都会有自己的文件系统:
而 Node
也有自己的文件系统操作模块。就是 fs(File System)
。
借助于 Node
帮我们封装的文件系统,我们可以在任何的操作系统(window、Mac OS、Linus)上面直接去操作文件。这也是 Node
可以开发服务器的一大原因,也是它可以成为前端自动化脚本等热门工具的原因。
Node
文件系统的 API
非常多,这些 API
大多数都提供了三种操作方式:
Promise
操作文件:代码不会被阻塞,通过 fs.promises
调用方法操作,会返回一个 Promise
,可以通过 then
、catcth
进行处理本章我们呢会介绍最常用的几种 API
。贴一下 文档地址,没介绍到的就去查文档吧。
拒绝摆烂ヾ(◍°∇°◍)ノ゙
从今天开始(2023/02/12
),定一个小目标,先刷个 300
道 Leetcode
题目(之前刷的不计入)。
当然作为一个小前端,我选择的语言是 TS
,而且刷的题目的难度会偏中等一些,大概按照 简单3
中等6
困难1
这样的题型分布吧。嗯,目前是这么打算的。
本题 Github 地址:因为比较喜欢 vscode
的界面,而且方便调试,所以 AC
完就顺便提到 github
了,也算做一个记录吧。
本篇的题目是这个系列的第
NO.26
:15. 三数之和NO.27
:16. 最接近的三数之和NO.28
:18. 四数之和排序算法就是研究如何对一个集合进行高效排序的算法,也是在面试时非常常见的面试题型之一。
下面是维基百科堆排序算法的解释:
在计算机科学与数学中,一个排序算法(Sorting algorithm) 是一种能将一串资料依照特定排序方式排列的算法。
在计算机科学所使用的排序算法通常依以下标准分类:
常见的排序算法