Demystifying RPC: From OSI Layers to Node.js JSON‑RPC Implementation

This article explains the fundamentals of Remote Procedure Call (RPC), explores how data moves across OSI layers, compares HTTP and RPC, and provides a complete Node.js JSON‑RPC example with code, error handling, and real‑world use cases such as Chrome DevTools Protocol.

Goodme Frontend Team
Goodme Frontend Team
Goodme Frontend Team
Demystifying RPC: From OSI Layers to Node.js JSON‑RPC Implementation

Background

Some team members work with hardware devices and need to understand device control and inter‑device communication; others often hear about RPC from backend developers, prompting a deeper look.

Understanding RPC

RPC (Remote Procedure Call) lets programmers invoke methods on remote services as easily as local function calls, abstracting away network communication.

How Data Travels Between Applications

Review of the OSI Model

The OSI model provides a layered view of network protocols, though not every communication uses all layers.

Typical user actions (browser navigation, messaging) follow the TCP/IP four‑layer model, with data passing through addressing, connection establishment, and transmission stages.

Typical Communication Steps

Domain name resolution (DNS)

TCP connection establishment (three‑way handshake)

Data exchange

Connection termination (four‑way handshake) with safeguards for lost ACKs

Why Use RPC?

In a scenario where a product service needs to verify inventory from an inventory service, RPC enables direct method calls between services, offering better performance than HTTP for internal communication.

HTTP/1.1 adds many headers and formatting overhead unnecessary for service‑to‑service calls, whereas RPC can be more lightweight and customizable.

RPC typically resides at the session layer of the OSI model and can be built on HTTP/WebSocket, TCP/UDP, or even the physical layer; most implementations use TCP, with gRPC built on HTTP/2.

Implementing RPC Over HTTP (JSON‑RPC)

JSON‑RPC is a lightweight RPC protocol that uses JSON for data exchange over HTTP or other transports.

JSON‑RPC is a lightweight remote‑call protocol that uses JSON as the data format, supporting simple, easy‑to‑use communication.

Key differences from a normal HTTP request:

POST body contains a JSON object instead of key/value pairs.

Server parses the JSON and dispatches based on method and params.

Response header Content‑Type becomes application/json-rpc.

Node.js + HTTP + JSON‑RPC Example

Error Object Design

type ErrorBody = {
  code: number; // error code
  message: string; // description
  data?: any; // optional additional info
};

Request Object Design

type RequestBody = {
  jsonrpc: string; // version, must be "2.0"
  method: string; // method name, prefixed with "rpc"
  params?: any; // structured parameters
  id: number | string; // unique identifier
};

Response Object Design

type ResponseBody = {
  jsonrpc: string; // must be "2.0"
  result?: any; // present on success
  error?: ErrorBody; // present on failure
  id: number | string; // matches request ID
};

JSON‑RPC Class Implementation

export default class JSONRPC {
  version: string = "2.0";
  errorMsg = {
    [-32700]: "Parse Error.",
    [-32600]: "Invalid Request.",
    [-32601]: "Method Not Found.",
    [-32602]: "Invalid Params.",
    [-32603]: "Internal Error.",
  };
  methods = {};
  normalize(rpc, obj) {
    obj.id = rpc && typeof rpc.id === "number" ? rpc.id : null;
    obj.jsonrpc = this.version;
    if (obj.error && !obj.error.message) {
      obj.error.message = this.errorMsg[obj.error.code] || obj.error.message;
    }
    return obj;
  }
  /**
   * Handle a JSON‑RPC request
   */
  handleRequest(rpc, response) {
    const method = this.methods[rpc.method];
    if (typeof method !== "function") {
      return response(this.normalize(rpc, { error: { code: -32601 } }));
    }
    try {
      response(this.normalize(rpc, { result: method.apply(this, rpc.params) }));
    } catch (error) {
      if (error instanceof Error) {
        response(this.normalize(rpc, { error: { code: -32000, message: error.message } }));
      } else {
        response(this.normalize(rpc, { error: { code: 0, message: "unknown error" } }));
      }
    }
  }
}

Starting an HTTP Server

import { createServer } from "http";
import url from "url";
import JSONPRC from "./rpc";

const HOST = "localhost";
const PORT = 8080;
const RPC = new JSONPRC();
RPC.methods = {
  rpcDivide(a, b) {
    if (b === 0) throw Error("Not allow 0");
    return a / b;
  },
};
const routes = {
  "/rpc-divide": (request, response) => {
    if (request.method === "POST") {
      let data = "";
      request.setEncoding("utf8");
      request.addListener("data", chunk => { data += chunk; });
      request.addListener("end", () => {
        RPC.handleRequest(JSON.parse(data), obj => {
          const body = JSON.stringify(obj);
          response.writeHead(200, {
            "Content-Type": "application/json",
            "Content-Length": Buffer.byteLength(body),
          });
          response.end(body);
        });
      });
    } else {
      response.end("hello nodejs http server");
    }
  },
};
const server = createServer((request, response) => {
  const pathname = url.parse(request.url || "").pathname || "";
  const route = routes[pathname];
  if (route) {
    route(request, response);
  } else {
    response.end("hello nodejs http server");
  }
});
server.listen(PORT, HOST, 0, () => {
  console.log(`server is listening on http://${HOST}:${PORT} ...`);
});

Running Result

Postman shows the JSON‑RPC response; malformed requests trigger the defined error handling.

RPC in the Front‑End World

Chrome DevTools Protocol (CDP)

CDP is Chrome's debugging protocol built on JSON‑RPC; the frontend communicates with the backend via WebSocket.

JSON‑RPC Use Case in Retail

Tablets used by store staff communicate with devices and modules through JSON‑RPC, enabling seamless control.

Summary

RPC abstracts network programming, allowing remote calls to feel like local method invocations.

Implementations can be based on HTTP/1.1, HTTP/2, WebSocket, TCP, UDP, etc.

RPC and HTTP serve different purposes; each fits specific scenarios.

JSON‑RPC leverages the JSON standard, offering high compatibility, lightweight design, and ease of use.

backend developmentRPCgRPCProtocolChrome DevToolsJSON-RPC
Goodme Frontend Team
Written by

Goodme Frontend Team

Regularly sharing the team's insights and expertise in the frontend field

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.