blog
blog copied to clipboard
Nodejs精简笔记教程
Table of Contents generated with DocToc
-
Nodejs权威指南读书笔记
- Nodejs介绍
-
Nodejs基础
- 控制台
- Nodejs中的全局作用域和全局函数
- __filename变量和__dirname变量
-
事件处理机制及事件环机制
- EventEmitter类
- EventEmitter类的各个方法
- 获取指定事件处理函数的数量
- EventEmitter类自身所拥有的事件
-
模块与npm包
- 核心模块与文件模块
- 外部访问模块内成员
-
Buffer类
- 创建Buffer对象
- Buffer对象与字符串对象之间的转换
- Buffer对象与JSON对象相互转换
- 复制缓存数据
- Buffer类的类方法
-
文件系统操作
- 同步与异步
-
文件读写
- readFile和readFileSync
- writeFile和writeFileSync
- appendFile和appendFileSync
- open和openSync
- read和readSync
-
创建与读写目录
- mkdir和mkdirSync
- readdir和readdirSync
-
查看与修改文件或目录信息
- stat和lstat
- exists
- realpath
- utimes和utimesSync
- chmod和chmodSync
-
对文件或目录的其他操作
- rename和renameSync
- link和linkSync
- symlink和symlinkSync
- truncate
- rmdir
- watchFile
-
文件流
- 基本概念
- ReadStream
- WriteStream
- path模块
-
TCP与UDP数据通信
-
net模块
- 创建TCP服务器
- socket端口对象
- 创建TCP客户端
- dgram模块
-
net模块
-
创建HTTP和HTTPS服务器端
- HTTP服务器
- 进程与子进程
- 错误处理与断言处理
- 加密与压缩
- 其他模块
- 数据库访问
- Express
- WebSocket通信
Nodejs权威指南读书笔记
Nodejs介绍
Nodejs
的目标是提供一种简单的、用于创建高性能服务器及可在该服务器中运行的各种应用程序的开发工具。
Nodejs
可实现高性能服务器,V8 JavaScript引擎为Node
提供底层支持。
它是非阻塞型I/O和基于事件环机制的。
我们可以通过require
函数来引用模块,使用exports
将模块暴露出去。
Nodejs
包含了一些核心模块
- fs 用于操作文件及文件系统
- events 为事件处理提供一个基础类
- crypto 用于实现数据的加密解密处理
- buffer 用于实现二进制数据的存储与转换
- child_process 用于实现子进程的创建于管理
- http 用于实现HTTP服务器端及客户端
- https 用于实现HTTPS服务器端和客户端
- path 用于处理文件路径
- querystring 用于处理HTTP请求中使用的查询字符串
在Nodejs
中,可以直接使用require
函数来引用这些模块
var http = require('http')
Nodejs
中的一些类、函数和对象
类、函数及对象 | 描述 |
---|---|
Buffer类 | 用于为二进制数据的存储提供一个缓冲区 |
setTimeout函数 | 用于在指定时间到达时执行一个指定函数 |
clearTimeout函数 | 用于取消在setTimeout函数内指定的函数的执行 |
setInterval函数 | 用于指定每隔多少时间执行一个指定函数 |
clearInterval函数 | 用于取消在setInterval函数内指定的函数执行 |
require函数 | 用户加载模块 |
module对象 | 用于访问模块信息 |
process对象 | 用于访问进程信息 |
一个简单的示例:
var http = require('http')
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'})
res.write('<head><meta charset="utf-8"/>></head>')
res.end('你好\n')
}).listen(1337, '127.0.0.1')
console.log('Server running at http://127.0.0.1:1337/')
Nodejs基础
控制台
console.log
方法用于进行标准输出流的输出。
console.log('This is a test string')
console.error
方法用于进行标准错误输出流的输出,即向控制台输出一行错误信息。
console.error('This is a anerror string.')
console.dir
方法用于查看一个对象中的内容并且将该对象的信息输出到控制台中。
var user = {
name: 'Kaindy',
getName: function () { return this.name }
setName: function (name) { this.name = name }
}
console.dir(user)
console.time
和console.timeEnd
方法用于统计一段代码的执行时间
console.time('small loop')
for (let i = 0; i < 10000; i++) {}
console.timeEnd('small loop')
console.trace
方法用于将当前位置处的栈信息作为标准错误信息进行输出。
console.assert
方法用于对一个表达式的执行结果进行评估,如果表达式的执行结果为false
,则输出一个消息字符串并抛出AssertionError
异常。
Nodejs中的全局作用域和全局函数
在Nodejs
中存在一个全局作用域,可以在这个全局作用域中定义一些不需要任何模块的加载即可使用的变量、函数或类。同时,它也预先定义了一些全局方法和全局类。
在Nodejs
中定义了一个global
对象,代表Nodejs
的全局命名空间,任何全局变量、函数或对象都是这个对象的一个属性值。
console.log(global)
nodejs
中的一些全局函数:
-
setTimeout
:指定经过多少毫秒后执行回调函数,与客户端的setTimeout
行为一致。var testFunc = function (msg) { console.log(msg) } var timer = setTimeout(testFunc, 1000, 'this is a parameter')
-
clearTimeout
:清除指定的定时器。var timer = setTimeout(testFunc, 5000, 'this is a test') clearTimeout(timer)
-
setInterval
:指定间隔多少毫秒之后执行回调函数,与客户端的setInterval
行为一致。var testFunc = function (msg) { console.log(msg) } var timer = setInterval(testFunc, 1000, 'this is a interval')
-
clearInterval
:清除指定的setInterval
定时器clearInterval(timer)
在Nodejs
中,为上述的定时器对象定义了unref
方法和ref
方法。unref
方法可以取消回调函数的执行,在执行了取消操作后,仍然可以使用ref
方法恢复回调函数的执行。
在Nodejs
中可以使用require
函数来加载模块。
var foo = require('../foo.js')
var http = require('http')
在Nodejs
中,定义了一个require.main
变量,用来检测一个模块是否为应用程序中的主模块。
if (module === require.main) {
console.log('is main module')
}
require.resolve
函数用来查询某个模块文件的文件名,这个文件名是带有完整的绝对路径的。
require.resolve('node.js') // 'E:\\nodejs\\node.js
require.cache
对象代表缓存了所有已被加载模块的缓存区。
// 查看缓存区
console.log(require.cache)
__filename变量和__dirname变量
在Nodejs
中,预定义了两个变量:用于获取当前模块文件名的__filename
变量与用于获取当前目录名的__dirname
变量。
在任何模块文件内部,都可以使用__filename
变量来获取当前模块文件带有完整绝对路径的文件名
// 在任意模块文件中写入代码
console.log(__filename)
// 执行这个模块文件
> node node.js // E:\nodejs\node.js
在任何模块文件内部,可以使用__dirname
变量获取当前模块文件所在目录的完整绝对路径
console.log(__dirnmae)
事件处理机制及事件环机制
与客户端浏览器中的事件一样,Nodejs
中也存在事件机制,比如htt.Server
对象会触发"接受到客户端请求"、"产生链接错误"等事件。
EventEmitter类
在Nodejs
中的用于实现各种事件处理的event
模块中,定义了一个EventEmitter
类,所有触发事件的对象都是一个继承了EventEmitter
类的子类的实例对象。EventEmitter
类也定义了很多实例方法用于处理各种事件。
方法 | 描述 |
---|---|
addListener(event, listener) | 对指定事件绑定事件处理函数 |
on(event, listener) | addListener 的别名,功能一致 |
once(event, listener) | 对指定事件指定只执行一次的事件处理函数 |
removeListener(event, listener) | 对指定事件解除事件处理函数 |
removeAllListeners([event]) | 对指定事件移除所有事件处理函数 |
setMaxListeners(n) | 指定事件处理函数的最大数量 |
listeners(event) | 获取指定事件的所有事件处理函数 |
emit(event,[arg1], [arg2], [...]) | 手动触发指定事件 |
EventEmitter类的各个方法
EventEmitter
类的on
方法或addListener
方法用于对指定事件绑定事件处理函数。
emitter.on(event, listener)
emitter.Listener(event, listener)
其中第一个参数是指定的事件名,第二个参数是该事件的事件处理函数。
var http = require('http') // 引用http模块
var server = http.createServer() // 创建服务器
// 为server服务器在接收到客户端的request请求时绑定事件处理函数
server.on('request', function (req, res) {
console.log(req.url)
res.end()
})
server.listen(1337, '127.0.0.1')
我们还可以通过on
方法对同一事件绑定多个事件处理函数。
var http = require('http')
var server = http.createServer()
server.on('request', function (req, res) {
// 干一些事
})
server.on('request', function (req, res) {
// 干另外一些事
})
...
默认情况下,同一事件最多可绑定10个事件处理函数。可以通过setMaxListeners
方法来修改最多可绑定的事件处理函数的数量。
要解除事件绑定,可以使用removeListener
方法
server.removeListener('request', testFunc)
removeAllListeners
方法用于解除某个事件的所有已被指定事件处理函数
emitter.removeAllListeners([event])
emit
方法用于手动触发一个事件。
emitter.emit(event, [arg1], [arg2], [...])
var http = require('http')
var server = http.createServer()
server.on('customEvent', function (arg1, arg2, arg3) {
console.log('自定义事件触发。')
console.log(arg1)
console.log(arg2)
console.log(arg3)
})
// 手动触发自定义事件
server.emit('customEvent', '自定义参数1', '自定义参数2', '自定义参数3')
server.listen(1337, '127.0.0.1')
获取指定事件处理函数的数量
EventEmitter
类自身拥有一个listenerCount
方法,用于获取某个对象的指定事件的处理函数数量。
EventEmitter.listenerCount(emitter, event)
第一个参数是指定的对象,第二个参数是事件名
var http = require('http')
var events = require('events')
var server = http.createServer()
server.on('request', function (req, res) {
if (req.url !== '/favicon.ico') {
console.log('接收到客户端请求')
}
})
server.on('request', function (req, res) {
if (req.url !== '/favicon.ico') {
console.log(req.url)
}
})
server.on('request', function (req, res) {
if (req.url !== '/favicon.ico') {
console.log('发送完毕')
}
})
server.listen(1337, '127.0.0.1')
console.log(events.EventEmitter.listenerCount(server, 'request'))
EventEmitter类自身所拥有的事件
在events
模块中,EventEmitter
类自身有两个事件:newListener
事件和removeListener
事件。
任何时候,对继承了EventEmitter
类的子类的实例对象绑定事件处理函数时,都将触发newListener
事件
emitter.on('newListener', function (e, f) {
// ...
})
同样,任何时候取消对继承了EventEmitter
类的子类的实例对象绑定的事件时,都将触发EventEmitter
类的removeListener
事件。
emitter.on('removeListener', function (e, f) {
// ...
})
模块与npm包
核心模块与文件模块
在Nodejs
中,以模块为单位划分所有的功能,一个Nodejs
应用程序由大量的模块组成,每一个模块都是一个JavaScript脚本文件。若需要加载模块,可以使用require
方法。
外部访问模块内成员
在一个模块文件内部定义的变量、函数或对象只在当前模块中有效,若需要从外部访问它们,则需要使用exports
方法。
var myMsg = 'hello'
var myFunc = function () {
return 'I\'m function'
}
exports.msg = myMsg
exports.myFunc = myFunc
将上述代码保存为文件,在需要的地方引入
var foo = require('./foo.js')
console.log(foo.msg) // 'hello'
console.log(foo.myFunc()) // 'I'm function'
同时也可以将模块定义为一个类,然后使用module.exports
将这个类导出。
var foo = function (name, age) {
this.name = name
this.age = age
}
foo.prototype.getName = function () {
return this.name
}
foo.prototype.setName = function (name) {
this.name = name
}
foo.prototype.getAge = function () {
return this.age
}
foo.prototype.setAge = function (age) {
this.age = age
}
module.exports = foo
Buffer类
在Nodejs
中,定义了一个Buffer
类,该类用来创建一个专门存放二进制数据的缓存区
创建Buffer对象
在Nodejs
中,Buffer
类是一个可以在任何模块中直接被引用的全局类。我们可以使用new
关键字来创建该类的实例对象。Buffer
类有三种形式的构造函数。
第一种是只需将缓存区大小指定为构造函数的参数:
new Buffer(size)
被创建的Buffer
对象有一个length
属性,表示缓存区大小
buf = new Buffer(128)
buf.length // 128
可以使用Buffer
对象的fill
方法来初始化缓存区中的所有内容。
buf.fill(value, [offset], [end])
第二种形式的构造函数是直接使用一个数组来初始化缓存区
new Buffer(array)
> buf = new Buffer([0, 1 ,2])
// <Buffer 00 01 02>
第三种形式是构造函数直接使用一个字符串来初始化缓存区。
new Buffer(str, [encoding])
第一个参数是初始化的字符串,第二个是编码,默认为utf8
> buf = new Buffer('Hello World')
// <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>
Buffer对象与字符串对象之间的转换
我们可以使用Buffer
对象的toString
方法将Buffer
对象中保存的数据转换为字符串。
buf.toString([encoding], [start], [end])
> buf
<Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>
> buf.toString()
'Hello World'
如果需要向Buffer
对象中写入字符串,则可使用write
方法。
buf.write(string, [offset], [length], [encoding])
在Nodejs
中,也可以使用StringDecoder
对象将Buffer
中的数据转为字符串,它与toString
方法行为一致,但对utf8
支持的更好。
Buffer对象与JSON对象相互转换
在Nodejs中,可以使用JSON.stringify
方法将Buffer
对象中保存的数据转换为一个字符串,也可以使用JSON.parse
方法将一个经过转换后的字符串还原为一个数组。
> buf = new Buffer('hello world')
<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
> json = JSON.stringify(buf)
'{"type":"Buffer","data":[104,101,108,108,111,32,119,111,114,108,100]}'
> JSON.parse(json)
{ type: 'Buffer',
data: [ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 ] }
> copy = new Buffer(JSON.parse(json))
<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
> copy.toString()
'hello world'
复制缓存数据
当有需要复制Buffer
中的二进制数据时,可以使用copy
方法
buf.copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd])
> buf2 = new Buffer(128)
<Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
... >
> buf.copy(buf2)
11
> buf2
<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
... >
Buffer类的类方法
Buffer
类定义了四个类方法(相当于静态方法)
-
isBuffer
方法,判断一个对象是否为Buffer
对象Buffer.isBuffer(obj)
-
byteLength
方法,计算一个指定字符串的字节数Buffer.byteLength(string, [encoding])
-
concat
方法,用于将多个Buffer
对象组合起来创建新的Buffer
对象Buffer.concat(list, [totalLength])
-
isEncoding
方法,用于检测一个字符串是否为一个有效的编码格式字符串Buffer.isEncoding(encoding)
文件系统操作
在Nodejs中,提供一个fs
模块,用于实现文件及目录的读写操作。
同步与异步
在Nodejs中,使用fs
模块来实现所有对文件及目录的创建、写入及删除操作。在fs
模块中,所有的方法都有同步和异步两种。比如:readFile
方法和readFileSync
方法,含有Sync
字符的方法均为同步方法,其他为异步方法。
// 同步方法读取文件,立即返回操作结果,会阻塞后续操作
var fs = require('fs')
var data = fs.readFileSync('./index.html', 'utf8')
// 等待操作返回结果
console.log(data)
// 异步方法读取文件,不阻塞后续操作,通过回调函数执行
fs.readFile('./index.html', 'utf8', function (err, data) {
consol.elog(data)
})
在大多数情况下,我们应该使用异步方法,但在很少的场景下,比如读取配置文件以启动服务器,应该使用同步方法。
文件读写
我们可以使用fs
模块中的readFile
方法或readFileSync
方法来读取文件。
readFile和readFileSync
fs.readFile(filename, [options], callback)
filename
参数和callback
参数为必填,分别是完整文件路径及文件名和回调函数。options
参数为一个对象,可以使用flag
属性指定对该文件执行什么样的操作,默认为r
-
r
:读取文件,文件不存在抛出异常 -
r+
:读取并写入文件,不存在抛出异常 -
rs
:以同步方式读取文件并通知操作系统忽略本地文件系统缓存,不存在抛出异常 -
w
:写入文件,文件不存在则创建该文件,已存在则清空文件内容 -
wx
:与w
相似,但以排他方式写入文件 -
w+
:读取并写入文件,文件不存在则创建,已存在则清空文件内容 -
wx+
:与w+
相似,以排他方式打开文件 -
a
:追加写入文件,文件不存在则创建 -
ax
:与a
相似,以排他方式打开文件 -
a+
:读取并追加写入文件,文件不存在则创建 -
ax+
:与a+
相似,以排他方式打开文件
除flag
之外,还可以使用encoding
属性指定以何种编码读取文件,属性值为utf8
、ascii
和base64
回调函数callback
如下:
function (err, data) {
// ...
}
// 读取文件示例
var fs = require('fs')
fs.readFile('./test.txt', function (err, data) {
if (err) console.log('读取文件时发生错误')
console.log(data)
// <Buffer 4e 6f 64 65 2e 6a 73 20 69 73 20 47 6f 6f 64 21 0d 0a 4a 61 76 61 53 63 72 69 70 74 20 69 73 20 47 6f 6f 64 21>
})
打印的结果是缓存区里的二进制结果,如果想要字符串,可以使用data.toString()
方法,或指定readFile
的字符编码参数为utf8
除了上述使用异步方法readFile
读取文件之外,还可以使用readFileSync
同步方法来读取文件
var data = fs.readFileSync(filename, [options])
参数含义与上述的异步方法一样。
var fs = require('fs')
try {
var data = fs.readFileSync('./test.txt', 'utf8')
console.log(data)
} catch (ex) {
console.log('读取文件时发生错误')
}
writeFile和writeFileSync
写入文件,可以使用fs
模块的writeFile
方法和writeFileSync
方法。
fs.writeFile(filename, data, [options], callback)
其中的options
参数对象可以使用flag
属性指定对文件执行何种操作,mode
属性指定对该文件的读写权限,encoding
属性指定以何种编码写入文件。
var fs = require('fs')
fs.writeFile('./input.txt', 'Hello\r\nWorld', function (err) {
if (err) console.log('写入文件失败')
console.log('写入文件成功')
})
下面的示例演示追加写入数据
var fs = require('fs')
var options = {
flag: 'a'
}
fs.writeFile('./test.txt', 'JavaScript', options, function (err) {
if (err) console.log('追加数据失败')
console.log('追加写入数据成功')
})
同步的写入内容使用writeFileSync
方法:
fs.writeFileSync(filename, data, [options])
appendFile和appendFileSync
当我们需要向文件末尾追加数据时,可以使用appendFile
或appendFileSync
方法。
fs.appendFile(filename, data, [options], callback)
var fs = require('fs')
fs.appendFile('./test.txt', '这是追加的数据', 'utf8', function (err) {
if (err) console.log('追加数据失败')
console.log('追加数据成功')
})
同步追加数据操作如下:
fs.appendFileSync(filename, data, [options])
open和openSync
如果我们要从指定位置开始读写文件,需要先使用fs
模块的open
方法或openSync
方法打开文件。
fs.open(filename, flags, [mode], callback)
这两个方法返回一个文件句柄。
var fs = require('fs')
fs.open('./test.txt', 'r', function (err, fd) {
console.log(fd)
})
同步打开
var fd = fs.openSync(filename, flags, [mode])
read和readSync
在打开文件获取到文件句柄后,可以使用read
方法,读取文件
fs.read(fd, buffer, offset, length, positon, callback)
写入文件内容使用fs
模块的write
方法或writeSync
方法。
fs.write(fd, buffer, offset, length, position, callback)
fs.writeSync(fd, buffer, offset, length, position)
创建与读写目录
mkdir和mkdirSync
在fs
模块中,可以使用mkdir
方法创建目录。
fs.mkdir(path, [mode], callback)
var fs = require('fs')
fs.mkdir('./test', function (err) {
if (err) console.log('创建目录失败')
console.log('创建目录成功')
})
以同步的方式创建目录,使用mkdirSync
方法
fs.mkdirSync(path, [mode])
readdir和readdirSync
在fs
模块中,使用readdir
方法读取目录
fs.readdir(path, callback)
var fs = require('fs')
fs.readdir('./', function (err, files) {
if (err) console.log('读取目录失败')
console.log(files)
// [ '.node.js.swp', 'input.txt', 'node.js', 'test', 'test.txt' ]
})
同步读取使用readdirSync
方法
var files = fs.readdirSync(path)
查看与修改文件或目录信息
stat和lstat
在fs
模块中,使用stat
方法或lstat
方法查看一个文件或目录的信息。
fs.stat(path, callback)
fs.lstat(path, callback)
回调函数如下:
function (err, stats) {
// ...
}
其中,stats
参数表示一个fs.Stats
对象,它有如下一些方法:
-
isFile
:判断是否为一个文件 -
isDirectory
:判断是否为一个目录 -
isBlockDevice
:判断是否为一个块设备文件。 -
isCharacterDevice
:判断是否为一个字符设备文件。 -
isSymbolicLink
:判断是否为一个符号链接文件。 -
isFIFO
:判断是否为一个FIFO文件 -
isSocket
:判断是否为一个socket文件。
exists
在fs
模块中,使用exists
方法检查一个文件或目录是否存在。
fs.exists(path, function (exists) {
// 参数exists为true,该文件或目录存在,否则不存在。
})
realpath
获取文件或目录的绝对路径使用realpath
方法。
fs.realpath(path, [cache], callback)
utimes和utimesSync
在fs
模块中,使用utimes
方法修改文件的访问时间及修改事件。
fs.utimes(path, atime, mtime, callback)
参数atime
用于指定修改后的访问时间,参数mtime
用于指定修改时间
同步方式修改使用utimesSync
方法
fs.utimesSync(path, atime, mtime)
chmod和chmodSync
在fs
模块中,使用chmod
方法修改文件或目录的读写权限。
fs.chmod(path, mode, callback)
参数mode
用于指定修改后的文件或目录的读写权限。
以同步方式修改文件或目录的读写权限,使用chmodSync
方法
fs.chmodSync(path, mode)
对文件或目录的其他操作
rename和renameSync
在fs
模块中,可以使用rename
方法移动文件或目录
fs.rename(oldPath, newPath, callback)
以同步方式移动文件或目录,使用renameSync
方法
fs.renameSync(oldPath, newPath)
link和linkSync
在fs
中,使用link
方法创建文件的硬链接,同步操作使用linkSync
fs.link(scrpath, dstpath, callback)
symlink和symlinkSync
在fs
中,使用symlink
方法创建文件或目录的符号链接,同步操作使用symlinkSync
。
fs.symlink(srcpath, dstpath, [type], callback)
truncate
在fs
模块中,使用truncate
方法对文件进行截断操作
fs.truncate(filename, len, callback)
rmdir
在fs
模块中,使用rmdir
方法删除空目录。
fs.rmdir(path, callback)
watchFile
在fs
模块中,使用watchFile
对文件进行监视。
fs.watchFile(filename, [options], listener)
文件流
基本概念
在应用程序中,流是一组有序的、有起点和终点的字节数据的传输手段。在应用程序中各种对象之间交换与传输数据的时候,总是先将该对象中所包含的数据转换为各种形式的流数据,在通过流传输,到达目标对象后再将流数据转换为该对象可用的数据。
ReadStream
在fs
模块中,使用createReadStrema
方法创建一个将文件内容读取为流数据的ReadStream
对象
fs.createReadStream(path, [options])
options
参数是一个对象,可能的值如下:
-
flags
:对文件采取什么样的操作,默认为r
-
encoding
:指定使用什么编码来读取该文件 -
autoClose
:指定是否关闭在读取文件时操作系统内部使用的文件描述符,默认为true
-
start
:使用整数值来指定文件的开始读取位置 -
end
:使用整数值来指定文件的结束读取位置
var fs = require('fs')
var file = fs.createReadStream('./test.txt', { start:1, end:12 })
file.on('open', function (fd) {
console.log('开始读取文件')
})
file.on('data', function (data) {
console.log('读取到数据')
console.log(data)
})
file.on('end', function () {
console.log('文件已全部读取完毕')
})
file.on('close', function () {
console.log('文件被关闭')
})
file.on('error', function (err) {
console.log('读取文件失败')
})
WriteStream
在fs
中,可以使用createWriteStream
方法创建一个将流数据写入文件中的WriteStream
对象
fs.createWriteStream(path, [options])
path模块
在Nodejs中,提供一个path
模块,它具有以下方法:
方法 | 描述 | 示例 |
---|---|---|
normalize |
该方法将非标准路径字符串转换为标准路径字符串 | path.normalize(p) |
join |
该方法将多个参数值字符串结合为一个路径字符串 | path.join([path1], [path2], [...]) |
resolve |
该方法以应用程序为起点,根据所有的参数值字符串解析出一个绝对路径 | path.resolve(path1, [path2], [...]) |
relative |
该方法用于获取两个路径之间的相对关系 | path.relative(from, to) |
dirname |
该方法用于获取一个路径中的目录名 | path.dirname(p) |
basename |
该方法用于获取一个路径中的文件名 | path.basename(p, [ext]) |
extname |
该方法用于获取一个路径中的扩展名 | path.extname(p) |
path.sep |
该属性值为操作系统指定的文件分隔符 | path.sep |
path.delimiter |
该属性值为操作系统指定的路径分隔符 |
TCP与UDP数据通信
在Nodejs
中,提供一个net
模块和一个dgram
模块,分别用于实现基于TCP和UDP的数据通信。
net模块
在Nodejs
中,使用net
模块实现TCP通信
创建TCP服务器
在Nodejs
中,调用net
模块中的createServer
方法创建TCP服务器
var server = net.createServer([options], [connectionListener])
options
选项是一个对象,其中包含一个布尔类型的allowHalfOpen
属性,默认为false
。
connectionListener
参数指定当客户端与服务器简历连接时调用的回调函数:
function (socket) {
// ...
}
当客户端与服务器建立连接时,触发connection
事件,我们可以监听此事件来调用回调函数
server.on('connection', function (socket) {
// ...
})
在创建了TCP服务器后,可以使用listen
方法通知服务器开始监听客户端连接。
server.listen(port, [host], [backlog], [callback])
上面的参数中,port
指定端口,host
指定主机名,backlog
指定最大连接数,默认值为511.
var net = require('net')
var server = net.createServer(function (socket) {
console.log('客户端与服务器端连接已建立')
})
server.listen(8431, 'localhost', function () {
console.log('服务器开始监听')
})
创建TCP服务器之后,可以使用address
方法查看该服务器所监听的地址信息
var address = server.address()
我们还可以使用getConnections
方法查看当前与TCP服务器建立连接的客户端数量
server.getConnections(function (err, count) {
console.log(count)
})
TCP服务器还可以设置一个整数类型的maxConnections
属性值,用于指定TCP服务器可以接收的客户端连接最大数量。
最后,我们可以使用close
方法显式的指定服务器拒绝所有新的客户端连接。
server.close(function () {
// ...
})
socket端口对象
在Nodejs
中,使用net.Socket
代表一个socket
端口对象。
创建TCP客户端
在Nodejs
中,创建TCP客户端只需创建一个用于连接TCP服务器的socket
端口对象即可。
var net = new net.Socket([options])
// 创建服务器端
var net = require('net')
var server = net.createServer()
server.on('connection', function (socket) {
console.log('客户端与服务器端连接已建立')
socket.setEncoding('utf8')
socket.on('data', function (data) {
console.log('已接收到客户端发送的数据:' + data)
if (data === 'Hello Nodejs') {
socket.write('数据已被确认:OK!')
} else {
socket.write('数据错误:Error!')
}
})
})
server.listen(8431, 'localhost')
// 创建客户端
var net = require('net')
var client = new net.Socket()
client.setEncoding('utf8')
client.connect(8431, 'localhost', function () {
console.log('已连接到服务器端')
client.write('Hello Nodejs!')
})
client.on('data', function (data) {
console.log('已接收到服务器端发送的数据:' + data)
})
dgram模块
TCP是一种基于连接的协议,通信之前客户端与服务器端必须先建立连接,而UDP是面向非连接协议,不需要建立连接,所以UDP是一种不可靠的协议,但速度很快。
在Nodejs
中,dgram
模块用来创建UDP服务器端和客户端。
创建HTTP和HTTPS服务器端
在Nodejs
中,提供http
模块和https
模块,用于创建HTTP或HTTPS服务器和客户端。
HTTP服务器
在Nodejs
中,使用http
模块中的createServer
方法创建HTTP服务器
var server = http.createServer(function (request, response) {
// ...
})
在回调函数中,第一个参数request
表示一个客户端请求对象,第二个参数response
表示一个服务器端响应对象。
在创建了HTTP服务器之后,使用listen
方法进行监听
server.listen(port, [host], [backlog], [callback])
var http = require('http')
var server = http.createServer(function (req, res) {
// ...
}).listen(1337, '127.0.0.1', function () {
console.log('服务器端开始监听')
})
可以使用close
方法关闭HTTP服务器
server.close()
可以监听服务器的关闭事件
server.on('close', function () {
// ....
})
当客户端与服务器端建立连接时,会触发HTTP服务器对象的connection
事件。
var http = require('http')
var server = http.createServer(function (req, res) {
// ...
}).listen(1337, '127.0.0.1')
server.on('connection', function (socket) {
console.log('客户端连接已建立')
})
HTTP服务器的setTimeout
方法用来设置服务器的超时时间
server.setTimeout(60 * 1000, function (socket) {
console.log('服务器超时')
console.log(socket)
})
另外,HTTP服务器有一个timeout
属性,属性值为整数值,单位为毫秒,可以用查看或修改服务器的超时时间
server.timeout = 1000
console.log(server.timeout)