NodeJS全集(四)

124 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

net 模块

通过研究 net 模块,可以帮助我们对网络请求有一个更深刻的认识。

回顾http请求

http请求是建立在TCP/IP协议上的。 tcp/ip 负责建立连接,htpp 协议则是规定请求的格式和文件类型。

http请求分为两种模式

  1. 普通模式:

通过三次握手建立连接,完成请求和响应,通过四次挥手断开连接。握手和挥手的都是操作系统完成的,我们只需要关心请求和完成响应。

  1. 长连接模式:

我们打开一个网页,会一次性请求很多的资源。如果使用普通模式的话,就会产生很多次的连接建立和断开的过程,造成响应时间增加很多。

在 http 请求头中将 Connection设为 keep-alive,表示开启了长连接。那么这次请求就不会自动的断开,客户端可以在一次连接中发送多个请求。

net

net 是一个通信模块,可以实现:进程间的通信 IPC,网络通信 TCP/IP。

创建客户端

// 开启一个socket
const net = require("net")
// 接收的数据
let receive = null;

// socket 是操作系统里的一个特殊的文件,跟网卡关联。
// 在node中表现为双工流对象
// 通过向流写入数据、获取数据
const socket = net.createConnection({
    host: "juejin.cn", // 主机地址
    port: 80
}, () => {
    console.log('连接成功');
})

socket.write(`GET / HTTP/1.1
Host: juejin.cn
Connection: keep-alive

`);

socket.on("close", () => {
    console.log(receive.body);
    console.log('请求结束');
})
// 得到响应的数据,进行处理
    socket.on("data", chunk => {
    // 根据响应头的 Content-Length 来判断是否传输完成
    const response = chunk.toString('utf-8');
    if (!receive) {
        receive = parseResponse(response);
        if (!isOver()) {
            socket.end();
        }
        return;
    }
    receive.body += response;
    if (!isOver()) {
        socket.end();
        return;
    }
})

// 辅助函数
/**
 * 提炼出响应字符串的消息头和消息体
 * @param {*} response 
 */
function parseResponse(response) {
    const index = response.indexOf("\r\n\r\n");
    const head = response.substring(0, index);
    const body = response.substring(index + 2).trimStart();
    const headParts = head.split('\r\n');
    const headArr = headParts.slice(1).map(str => {
        return str.split(":").map(s => s.trim())
    })
    const header = headArr.reduce((a, b) => {
        a[b[0]] = b[1];
        return a
    }, {})
    return {
        header,
        body
    }
}
// 判断是否接收完成
function isOver() {
    // 需要接收的消息体的总字节数
    const contentLength = +receive.header["Content-Length"];
    const curReceiveLength = Buffer.from(receive.body, 'utf-8').byteLength;
    return curReceiveLength >= contentLength;
}

创建服务器

const net = require('net');

const server = net.createServer();

server.listen(8081);//服务器监听端口8081

server.on('listening', ()=>{
    console.log("server is listening 8081");
})

处理请求

// 当连接到来会触发该函数, 得到一个socket对象
server.on("connection", socket => {
    console.log('接收连接');
    
    socket.on("data", chunk => {
        console.log(chunk.toString('utf-8'));

        socket.write(`HTTP/1.1 200 OK

<!doctype html>
<html lang='en'>
<head>
</head>
<body>
    <h1>你好</h1>
</body>
</html>`);
    socket.end();
    })
    socket.on("end", ()=>{
        console.log('连接关闭');
    })
})