nodeJS——net和http模块

291 阅读3分钟

客户端和服务器之间的通信可简单的理解为:客户端“请求”,服务器“响应”,一来一回就可以达成信息的传递。在浏览器客户端,可通过js(XMLHttpRequest)发起请求,在服务器端(nodeJS为例)中则是通过net或者http模块发送信息。

net模块

nodejs.org/dist/latest…
net模块对应TCP/IP协议,连接建立后后可发送任意形式的信息,只要通信双方约定好信息的格式,就能解读出发送的信息,是一种比较底层的通信使用方法。

客户端

const net = require("net");

// 第一步,与服务器建立连接
const socket = net.createConnection({
// socket是一个stream对象,向其“write”则发送信息,监听“data”事件则可获取信息
host: "baidu.com",
port: 9527,
}, () => {
console.log("连接成功");
});

// 第二步,发送请求
socket.write('需要发送的信息');
// net模块是一种比较底层的通信模块,就是单纯的发送信息,获取信息。如果需要进行http通信,则需要发送http格式的信息。
socket.write('GET / HTTP/1.1
Host: baidu.com
Connection: keep-alive

');

// 第三部,获取响应数据
socket.on('data', (chunk) => {
console.log(chunk);
});

服务器端

const net = require("net");
const server = net.createServer();
// 监听9527端口
server.listen(9527);

server.on('listening', () => {
    console.log('开始监听9527端口');
});

server.on('connection', (socket)=> {
    console.log("客户端连接完成");
    socket.on('data', (chunk) => {
        console.log('客户端发来的信息', chunk.toString('utf-8'));
        const Buf = Buffer.from(`HTTP/1.1 200 OK
Content-Type: image/jpeg

你好
`, 'utf-8');
        socket.write(Buf);
        socket.end();
    });
  
});

http通信是建立在TCP/IP协议基础上的,实际就是客户端发送固定格式的字符串,服务端收到信息,解析信息,将响应信息以相同格式发回客户端。

http模块

nodejs.org/dist/latest…
http模块对应http协议,http模块专门用于发送http请求,比net模块便利很多。

客户端

const http = require('http');
    // 客户端发送请求与ajax类似
    const request = http.request("url", {
    method: 'GET'
}, (resp) => {
    // console.log('来自服务器的响应信息', resp);
    console.log('响应头', resp.headers);
    console.log('状态码', resp.statusCode);
    let result = "";
    resp.on('data', (chunk) => {
        result += chunk.toString('utf-8');
    });

    resp.on('end', () => {
        console.log(JSON.parse(result));
    });
});

request.end(); //表示消息体结束

服务器端

const http = require('http');
const server = http.createServer(hanlder);
const server.listen(6100, () => {
    console.log('端口监听完成');
);

const hanlder = function (req, res) {
    console.log('客户端请求对象', req);
    // 发送响应消息
    res.write("hello");
    res.end();
}

了解http模块的使用方法后,可搭建一个简单的静态资源服务器

// http模块搭建服务器 搭一个静态资源服务器
const path = require('path');
// const URL = require("url");
const http = require('http');
const fs = require('fs');

// 判断文件是否存在
async function getStat(filename) {
    try {
        return await fs.promises.stat(filename);
    } catch {
        return null;
    }
}

async function getFileContent(url) {
    // console.log();
    // url.slice(1) 避免url一开始是'/',去到根目录
    let filename = path.resolve(__dirname, 'public', url.slice(1));
    let stat = await getStat(filename);
    if (!stat) {
        return null;
    } else if (stat.isDirectory()) {
        filename = path.resolve(__dirname, 'public', url.slice(1), 'index.html');
        stat = await getStat(filename);
        if (!stat) {
            return null;
        }
        // return await fs.promises.readFile(filename);
        return await fs.createReadStream(filename);
    }
    // return await fs.promises.readFile(filename);
    return await fs.createReadStream(filename);
}

async function hanlder(req, res) {
    const url = req.url;
    // console.log(url);
    // const result = await getFileContent(url);
    const rs = await getFileContent(url);
    if (rs) {
        rs.pipe(res);
        rs.on('close', () => {
            res.end();
        });

    } else {
        res.statusCode = 404;
        res.write("Resource is not exist");
        res.end();
    }


    // 若res.end()了,就不会触发drain事件(猜测所有Stream的事件应该都不触发)
    // res.end();
}

// 每有一次请求来都会执行一次handler
const server = http.createServer(hanlder);

server.listen(6100, () => {
    // console.log('端口监听完成');
});

server.on('listening', () => {
    console.log('监听6100端口');
});