Published on

Node 中的 net 模块

Authors
  • avatar
    Name
    Et cetera
    Twitter

net 模块

回顾 HTTP 相关

  • 普通模式: 通过三次握手建立连接、四次挥手关闭连接,进行请求交互(次数多浪费带宽资源等等)

  • 长链接模式: 通过三次握手建立连接,进行请求交互,但是不关闭连接,可以进行多次请求交互(connection: keep-alive),完成后四次挥手关闭连接

net 模块创建客户端

可以实现进程间的通信 IPC 和网络通信 TCP/IP

import * as net from 'net'

// 返回的 socket 是什么
// socket 是一个可读可写流(双工流)对象
// 作用:
// 通过向流中写入数据,向服务器发送数据
// 通过监听流的 data 事件,监听服务器返回的数据
// 是通过 TCP/IP 连接的远程服务器
const socket = net.createConnection({ host: 'github.com', port: 80 }, () => {
  console.log('连接成功')
})

// 需要对数据进行写的操作,服务器才会做响应
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
  }
})

// socket.write('a')

let receive = null

/**
 * 提炼出响应信息的消息头和消息体
 * @param response
 */
function parseResponse(response: string) {
  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
}

// 这样表示发送的是一个 HTTP 请求
socket.write(`GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive

`)

socket.on('close', () => {
  console.log(receive.body)
  console.log('连接关闭')
})

net 模块创建服务端

net 创建服务器,并返回图片资源

import net from 'net'
import path from 'node:path'
import fs from 'node:fs'

const server = net.createServer()

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

server.on('listening', () => {
  console.log('server listen 9527')
})

server.on('connection', (socket) => {
  console.log('有客户端连接到服务器')

  socket.on('data', async (chunk) => {
    // console.log(chunk.toString('utf-8'))
    const filename = path.resolve(__dirname, './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()
  })

  socket.on('end', () => {
    console.log('连接关闭了')
  })
})