回顾 http 请求
-
普通模式
-
长连接模式
net 模块能干什么
net 是一个通信模块
利用它,可以实现
进程间的通信 IPC
、网络通信 TCP/IP
通信事件和方法
API | 描述 |
---|---|
listening 事件 | 开始监听端口后触发的事件 |
connection 事件 | 新的连接建立时触发,服务端会返回一个 socket 双工流对象 |
close 事件 | 当连接关闭时触发,如果当前还有连接存在,直到所有连接都结束之后才会触发这个事件 |
error 事件 | 当错误出现的时候触发 |
data 事件 | 从可读流中消费数据的操作 |
end 事件 | 当数据被消费完成之后,可读流关闭之前触发,一般用于服务端 |
write 方法 | 用于写入数据,在 socket 上发送数据 |
end 方法 | 结束写入,有数据传人则代表最后一次写入 |
创建客户端
const net = require("net");
// 由于访问的服务端协议是 http,数据传输的格式必须满足 http 协议规范
// 如果访问的服务端是 tcp/ip,则数据格式没有限制,http 是基于 tcp/ip
const socket = net.createConnection(
{ host: "duyi.ke.qq.com", port: 80 },
() => console.log("连接成功")
);
/**
* 提炼出响应字符串的消息头和消息体
* @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);
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() };
}
var receive = null;
function isOver() {
// 需要接收的消息体的总字节数
const contentLength = +receive.header["Content-Length"];
const curReceivedLength = Buffer.from(receive.body, "utf-8").byteLength;
console.log(contentLength, curReceivedLength);
return curReceivedLength > contentLength;
}
socket.on("data", chunk => {
const response = chunk.toString("utf-8");
if (!receive) {
receive = parseResponse(response); // 只解析第一次,解析请求头
if (isOver()) {
socket.end();
return;
}
}else{
receive.body += response;
if (isOver()) {
socket.end();
return;
}
}
});
/**
* 请求行
* GET / HTTP/1.1
*
* 请求头
* Host: duyi.ke.qq.com
* Connection: keep-alive
*
* 请求体: 请求行后跟着两个换行符,之后的内容是请求体
*/
socket.write(`GET / HTTP/1.1
Host: duyi.ke.qq.com
Connection: keep-alive
`);
socket.on("close", () => {
console.log(receive.body);
console.log("结束了!");
});
创建服务端
const net = require("net");
const fs = require("fs");
const path = require("path");
const server = net.createServer();
server.listen(9527); // 服务器监听 9527 端口,浏览器访问 localhost:9527
// 开始监听端口后触发的事件
server.on("listening", () => {
console.log("server listen 9527");
});
server.on("connection", socket => {
// 每次连接都会返回一个 socket 对象
console.log("有客户端连接到服务器");
socket.on("data", async chunk => {
const filename = path.resolve(__dirname, "./hsq.jpg");
const bodyBuffer = await fs.promises.readFile(filename);
// http 协议规范
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();
});
socket.on("end", () => {
console.log("连接关闭了");
});
});
打赏作者
您的打赏是我前进的动力
微信
支付宝
node👉 文件流 stream
上一篇
评论