Node之net模块

Node之net模块

net 模块是建立在 tcp/ip 协议上的。同时还可以进行进程间的通信 ipc 。我们之前的 http 请求是一次请求一次响应。普通模式是三次握手之后进行一次请求和响应然后第四次挥手。长连接模式就是在握手和挥手之间不进行中断,直到客户端或者服务器有一方提出中断,使用 keep-alive连接方式。

而 tcp/ip 可以在握手和挥手之间传递任意数据,不受限制,不需要消息头,消息体。握手和挥手也是 tcp/ip 上的内容,它们在操作系统上被执行。我们只能在浏览器上看到请求和响应。

js 复制代码
const net = require('net')
const socket = net.createConnection({
    host: 'duyi.ke.qq.com',
    port: 80
}, () => {
    console.log('连接成功')
})
socket.on('data', chunk => {
    console.log(chunk.toString('utf-8'))
})
socket.write(`GET / HTTP/1.1
Host: duyi.ke.qq.com
Connection: keep-alive

`)

可以通过 net.createConnection 的方式创建一个客户端。会返回一个双工流 socket 。它是一个特殊的文件,与网卡相关联,可以随时写入读取。在进行读取前必须先写入数据。里面可以传入两个参数,第一个参数是配置对象,第二个参数是监听函数,它可以在完成连接之后调用。

这是因为 http 协议有固定的模式和格式。必须先进行请求然后才能拿到响应结果。请求的格式包括请求行,请求头,请求体。请求行一个换行到请求头,然后两个换行到请求体,请求体可以没有,但必须进行两次换行。

js 复制代码
const net = require('net')
const socket = net.createConnection({
    host: 'duyi.ke.qq.com',
    port: 80
}, () => {
    console.log('连接成功')
})
function parseResponse(response) {
    const index = response.indexOf('\r\n\r\n');
    const head = response.substring(0, index);
    const body = response.substring(index + 2);
    const headParts = head.split('\r\n');
    const headerArray = headParts.slice(1).map(str => {
        return str.split(':').map(s => s.trim())
    })
    const header = headerArray.reduce((a, b) => {
        a[b[0]] = b[1];
        return a;
    }, {})
    return {
        header,
        body: body.trimStart()
    }
}
function isOver() {
    const contentLength = receive.header['Content-Length'];
    const curReceivedLength = Buffer.from(receive.body, 'utf-8').byteLength;
    console.log(contentLength, curReceivedLength);
    return curReceivedLength > contentLength;
 }
let receive = null;
socket.on('data', chunk => {
    const response = chunk.toString('utf-8')
    if (!receive) {
        //第一次接受数据
        receive = parseResponse(response)
        if (isOver()) {
            socket.end()
        }
        return;
    }
    receive.body += response;
    if (isOver()) {
        socket.end()
        return;
    }
    console.log('来自服务器的消息');
});
socket.write(`GET / HTTP/1.1
Host: duyi.ke.qq.com
Connection: keep-alive

 `);
socket.on('close', () => {
    console.log(receive.body)
    console.log('关闭了');
});

我们将 header 里面的东西提取出来,变成一个对象。并找到对象里的 Content-Length 然后看是否当前的字符长度达到了要求的长度。如果第一次已经达到,就直接结束,如果没有达到,就在 body 里不断加入拿到的响应结果加进去,直到达到要求的字符长度。并在最后结束的时候将 body 输出。

js 复制代码
const fs = require('fs');
const path = require('path');
const server = net.createServer();
server.listen(8000);
server.on('listening', () => {
    console.log("server listen 8000")
})
server.on("connection", (socket) => {
    console.log("有新的连接");
    socket.on("data", async chunk => {
        const filename=path.resolve(__dirname, "./myfiles/avatar.jpeg");
        const bodyBuffer = await fs.promises.readFile(filename);
        const headBuffer = Buffer.from(`HTTP/1.1 200 OK
Content-Type: image/jpeg

`,
          "utf-8"
        );
        const result = Buffer.concat([headBuffer, bodyBuffer]);
        socket.write(result);
        socket.end();
    });
});
server.on("close", () => {
    console.log("server close")
});

创建一个服务器,可以传入一个监听函数,表示服务器是否创建。服务器需要监听一个端口,并且在监听之后可以通过 listening 事件得知。

当与客户端成功连接之后,会创建一个 socket ,即使是同一个客户端断开之后,也会重新创建一个 socket ,socket 在一次连接过后或者长时间断开之后销毁。使用 connection 可以监听连接。

可以读取客户端传来的 socket ,然后再写入 socket 作为响应结果。

在连接结束之后,关闭服务器。

相关推荐
r0ad1 分钟前
从痛点到解决方案:为什么我开发了Chrome元素截图插件
前端·chrome
OEC小胖胖8 分钟前
连接世界:网络请求 `wx.request`
前端·微信小程序·小程序·微信开放平台
jingling55521 分钟前
解决微信小程序真机调试中访问本地接口 localhost:8080 报错
前端·微信小程序·小程序
en-route22 分钟前
使用 Flask 构建 Web 应用:静态页面与动态 API 访问
前端·python·flask
IT_陈寒24 分钟前
Vite 5年迭代揭秘:3个核心优化让你的项目构建速度提升200%
前端·人工智能·后端
怎么吃不饱捏39 分钟前
vue3+vite,引入阿里巴巴svg图标,自定义大小颜色
前端·javascript·vue.js
无敌最俊朗@41 分钟前
MQTT 关键特性详解
java·前端·物联网
JAVA学习通41 分钟前
微服务项目->在线oj系统(Java-Spring)----[前端]
java·开发语言·前端
瓜瓜怪兽亚43 分钟前
前端基础知识---10 Node.js(三)
数据结构·数据库·node.js
excel1 小时前
Vue3 响应式系统核心执行器:Reactive Effect 与依赖调度机制
前端