2020-04-08
Node
0

目录

event
buffer
dgram
net
http

随着现代Web应用程序的发展,服务器端JavaScript平台Node.js越来越受欢迎。Node.js提供了一种快速、高效的方式来构建服务器端应用程序,并通过其强大的API来支持许多关键功能。无论您是初学者还是有经验的开发人员,了解Node.js API的基本概念和用法都是非常重要的。

本篇学习 event、buffer、dgram、net。

event

js
const EventEmitter = require('events'); const myEmitter = new EventEmitter(); myEmitter.on('event', () => { console.log('触发事件'); }); myEmitter.emit('event');

内置事件:

  • error:当 EventEmitter 实例出错时,应该触发 'error' 事件。
  • newListener:EventEmitter 实例在新的监听器被添加到其内部监听器数组之前,会触发自身的 'newListener' 事件。
  • removeListener: 'removeListener' 事件在 listener 被移除后触发。
js
const MyEmitter=require('events'); const myEmitter = new MyEmitter(); // 只处理一次,避免无限循环。 myEmitter.once('newListener', (event, listener) => { if (event === 'event') { // 在前面插入一个新的监听器。 myEmitter.on('event', () => { console.log('B'); }); } }); myEmitter.on('event', () => { console.log('A'); }); myEmitter.emit('event');

内置方法:

  • on(eventName, listener):注册事件监听器
  • once(eventName, listener):注册只被执行一次的事件监听器
  • off(eventName, listener):移除事件监听器
  • emit(eventName,...args):执行事件
  • addListener(eventName, listener):同on方法
  • removeListener(eventName, listener):同off方法
  • prependListener(eventName, listener):添加 listener 函数到名为 eventName 的事件的监听器数组的开头。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加多次。
  • prependOnceListener(eventName, listener):同上
  • removeAllListeners:移除事件
  • eventNames():返回当前已注册的事件名
  • getMaxListeners():获取当前监听器的最大限制个数
  • setMaxListeners(n):默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 这有助于发现内存泄露。 但是,并不是所有的事件都要限制 10 个监听器。 emitter.setMaxListeners() 方法可以为指定的 EventEmitter 实例修改限制。
  • listenerCount(eventName):返回正在监听的名为 eventName 的事件的监听器的数量。
  • listeners(eventName):返回名为 eventName 的事件的监听器数组的副本。
  • rawListeners(eventName):返回名为 eventName 的事件的监听器数组的拷贝。和listeners没啥区别,都无法都直接改变函数或者直接添加方法。唯一区别,是once调用方法

buffer

在了解buffer之前,先来了解下ASCII码、Unicode、UTF-8

ASCII码一个字符只占一个字节,一个字节最多可以展示256个符号(只能用来展示字母和符号)。不能用来展示中文

Unicode一个字符占两个字节,用十六进制编码而成(ASCII码编译成16进制),可以展示256*256个符号。英文,中文占2个字节

UTF-8:目前互联网最常见的Unicode编码方式,它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。英文占1个字节,中文3个字节

JS下unicode转换:

js
'a'.charCodeAt().toString(16) // charCodeAt转成10进制,unicode默认16进制,需要通过toString进行转换进制 // 61 let a='61' parseInt(a,16) // 将16进制的参数a,转换为10进制 // 97

Buffer.from:将数据转换为buffer

js
const buf = Buffer.from('abc','ascii'); // buffer格式=><Buffer 61 62 63> console.log(buf.toString('base64')) // 转换为base64编码格式,输出=>YWJj

Buffer.alloc:生成指定长度的buffer

js
const buf1 = Buffer.alloc(5); // 默认以0填充 console.log(buf1); // <Buffer 00 00 00 00 00> const buf2 = Buffer.alloc(5,'a'); // 默认以'a'的编码填充 console.log(buf2);// <Buffer 61 61 61 61 61> const buf3 = Buffer.alloc(5,'YWJj','base64'); // 将'YWJj'采用base64的编码形式 console.log(buf3);

Buffer.concat:将数组内的buffer整合成一个buffer对象

js
let arr=[Buffer.alloc(1),Buffer.alloc(2)] let bufArr=Buffer.concat(arr) console.log(bufArr)

dgram

server.js

js
const dgram = require('dgram'); const server = dgram.createSocket('udp4'); server.on('error', (err) => { console.log(`服务器异常:\n${err.stack}`); server.close(); }); server.on('message', (msg, rinfo) => { console.log(`服务器接收到来自 ${rinfo.address}:${rinfo.port}${msg}`); }); server.on('listening', () => { const address = server.address(); console.log(`服务器监听 ${address.address}:${address.port}`); }); server.bind(41234);

client.js

js
const dgram=require('dgram') const clientSocket=dgram.createSocket('udp4') clientSocket.send('hello',41234,'127.0.0.1',()=>{ // 向服务端发送请求 console.log('发送成功',clientSocket.address()) clientSocket.close() })

net

server.js

js
const net=require('net') const fs=require('fs') const server=net.createServer(()=>{ //这个函数其实就是connection事件绑定的函数 }) server.on('connection',(socket)=>{ console.log('有人连接了',socket.remoteAddress,socket.remotePort) let image=fs.readFileSync('./logo.png') socket.write(image) socket.end() socket.on('data',data=>{ socket.write('show me the money') }) }) server.listen(12345)

client.js

js
const net=require('net') const clientSocket=net.createConnection(12345) clientSocket.on('data',data=>{ console.log('服务器返回',data) // clientSocket.write('get money') }) clientSocket.on('end',()=>{ console.log('数据接收完成') })

http

开启服务

js
const http=require('http') const server = http.createServer() server.on('request',(req,res)=>{ console.log('接收到了请求',req.socket.address(),req.url) res.writeHead(200, { 'Content-Type': 'text/plain;charset=utf-8' }) res.end('响应内容') }) server.listen(6688)

发送请求

js
const http=require('http') const fs=require('fs') let client=http.request({ host:'www.baidu.com', port:80, protocol:'http:', method:'get', path:'/' },(res)=>{ let content='' res.on('data',data=>{ content+=data.toString() }) res.on('end',()=>{ fs.writeFileSync('./baidu.html',content) }) }) client.end()

静态资源服务

js
const fs=require('fs') const http=require('http') const server = http.createServer() function staticSend(res,fileName,headers={ 'Content-Type': 'text/html;charset=utf-8', },statusCode=200){ const ext=fileName.substr(fileName.lastIndexOf('.')+1) if(ext==='css'){ headers={ 'Content-Type': 'text/css;charset=utf-8', } } res.writeHead(statusCode, http.STATUS_CODES[statusCode],headers) res.end(fs.readFileSync(fileName)) } server.on('request',(req,res)=>{ console.log(req.url) if(req.url.indexOf('/static/')===0){ // url以/static/开头 if(fs.existsSync(__dirname+req.url)){ // 文件存在 staticSend(res,__dirname+req.url) } else{ // 文件不存在 res.writeHead(401, http.STATUS_CODES[404]) res.end() } return } res.writeHead(200, http.STATUS_CODES[200],{ 'Content-Type': 'text/html;charset=utf-8' }) switch (req.url) { case '/404': res.writeHead(404, http.STATUS_CODES[404]) res.end('<h1 style="color: red;">404</h1>'); break; default: res.end('<h1>响应内容</h1>') } }) server.listen(6688)

本文作者:BARM

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!