Node.js RPC 介绍和半双工简单代码实现(新手版)

什么是 RPC

本篇是极客时间杨浩老师的概括总结。首先点开这篇文章的你肯定会疑惑,什么是RPC呢?既然有了HTTP协议为什么还需要RPC?

RPC 与 HTTP 作比较

  1. RPC本质上不算是协议,而是一种调用方式
  2. RPC的实现是基于Socket之上的
  3. HTTP是90年代才开始流行的,在TCP之上之前有很多替代的协议,这就包括RPC,也就说在没有HTTP协议的时代,很多人用RPC发送数据的。

那为什么现在有了 HTTP 我们还需要学习 RPC 呢?

有一个比较直观的理解就是在 c/s 架构下 (client/server), RPC 可以使用在公司内网,进行数据传输。

RPC 的技术不同点

  1. 不一定使用DNS作为寻址服务(在内网里互相请求)
  1. RPC应用层协议通常不使用HTTP,而是采用基于二进制的协议来替代HTTP

RPC传输二进制协议,相比HTTP

  1. 更小的数据包体积

  2. 更快的编解码速率

  1. 基于TCP或UDP协议

RPC 技术实现

二进制传输实现

使用 Node.js 中的 Buffer API 详情见官网文档Buffer | Node.js v18.17.1 Documentation (nodejs.org)

这里需要掌握两个创建 Buffer 的语法,用于二进制传输

  1. Buffer.from
  • 可以接受多种输入类型作为参数,包括字符串、数组、Buffer对象
  • 提供的数据可以直接填充到Buffer中,const bufferFromStr = Buffer.from('Hello');
  • 如果提供了字符串,则可以指定编码格式,例如'utf8'、'hex'等,默认为'utf8'。
  1. Buffer.alloc
  • 创建指定大小的新的Buffer对象,并将所有字节设置为零(初始化)。
  • 接受一个整数参数,表示要分配的字节数。

RPC 半双工代码

server 端

js 复制代码
const net = require('net')

const server = net.createServer((socket) => {
    socket.on('data', function (buffer) {
        const fruitId = buffer.readInt32BE()
        const fruitData = data[fruitId];
        if(fruitData !== undefined) {
            const bufferc = Buffer.from(fruitData);
            setTimeout(() => {
                socket.write(bufferc);
            }, 500);
        } else {
            console.log("fruitId: " + fruitId + " doesn't exist.")
        }
        
        console.log(buffer, buffer.toString())
    })
})

const data = {
    136797: "01 草莓",
    136798:"02 香蕉",
    136799: "03 西瓜",
    136808: "04 榴莲",
    136801: "05 菠萝蜜",
    136803: "06 香瓜",
    136804: "07 白兰瓜",
}

server.listen(4000)

client 端

js 复制代码
const net = require('net')

const socket = new net.Socket({})

socket.connect({
    host: '127.0.0.1',
    port: 4000
})

const id = [
    "136797",
    "136798",
    "136799",
    "136808",
    "136801",
    "136803",
    "136804",
]

// 请求第一次发送
let index = Math.floor(Math.random() * id.length)
socket.write(encode(index))

socket.on('data', (buffer) => {
    const fruitBuffer = buffer;
    console.log(fruitBuffer.toString())

    index = Math.floor(Math.random() * id.length)
    socket.write(encode(index))
})

function encode(index) {
    let buffer = Buffer.alloc(4)
    buffer.writeInt32BE(
        id[index]
    )
    console.log(id[index])
    return buffer
}
相关推荐
sir.山13 分钟前
在 Vue 3 项目中使用 Mock 数据
前端·vue.js·vue3·vite
天涯明月199321 分钟前
SGLang深度研究报告
人工智能·后端·推理·sglang
李剑一23 分钟前
华为新上Pura X View阔直板手机,特殊屏幕比例设备下,前端应该怎么去适配更完美?送你一套完整工具代码
前端
01_ice33 分钟前
html个人简历展示
前端·html
程序员爱钓鱼39 分钟前
Rust where详解:让泛型与Trait约束更加清晰
前端·后端·rust
zzzzzz3102 小时前
react-bits 为什么会吸引前端开发者:别把动效当装饰,先把它当成页面能力
前端·react.js·动效
程序员爱钓鱼3 小时前
Go 编程实战:函数 Function——参数、返回值与代码复用
后端·面试·go
风月说与山鬼4 小时前
二、React入口文件(main.jsx)
前端·react.js
To_OC8 小时前
跑了3个Docker容器后,我终于搞懂镜像和容器到底啥关系
后端·docker·容器
东风破_9 小时前
Docker 基础:为什么需要容器?
前端·后端·nginx