Building a Real-Time Chat App with RPC: A Step-by-Step Guide

What is RPC?

RPC, or Remote Procedure Call, is a protocol that enables client-server applications to request procedures or function calls from a remote server. In this tutorial, we’ll explore how to build an RPC server in Go and an RPC client in Node.js.

Prerequisites

Before we dive in, make sure you have the following installed on your local machine:

  • Go
  • Node
  • Protocol buffer

Objectives

By the end of this article, you’ll have built a chat RPC server that sends messages and returns user details. The server will have two methods: SayHello, which accepts a message body, and GetDetails, which accepts a user’s name and age.

Creating the RPC Server

First, create a new project directory and change into it. Then, configure Protocol Buffer by creating a chat.proto file with the following code:


syntax = "proto3";
message Message {
string body = 1;
}
message Details {
string name = 1;
int32 age = 2;
}
message Response {
string body = 1;
}
service ChatService {
rpc SayHello(Message) returns (Response) {}
rpc GetDetails(Details) returns (Response) {}
}

This code defines a ChatService with two methods: SayHello and GetDetails. The SayHello method accepts a Message object and returns a Response object, while the GetDetails method accepts a Details object and returns a Response object.

Generating Go Code

Next, generate Go code based on the chat.proto file using the following command:


protoc --go_out=. chat.proto

This will generate a new folder named chat with the Go code.

Implementing Methods

Create a new file named chat.go and implement the SayHello and GetDetails methods:

“`
package main

import (
“context”
“log”

pb "chat"

)

type ChatServer struct{}

func (s ChatServer) SayHello(ctx context.Context, req *pb.Message) (pb.Response, error) {
log.Println(“SayHello Called”)
return &pb.Response{Body: req.Body}, nil
}

func (s ChatServer) GetDetails(ctx context.Context, req *pb.Details) (pb.Response, error) {
log.Println(“GetDetails Called”)
return &pb.Response{Body: fmt.Sprintf(“Hello, %s!”, req.Name)}, nil
}
“`

Configuring the Server

Create a new file named server.go and configure the server:

“`
package main

import (
“google.golang.org/grpc”
“log”
“net”

pb "chat"

)

func main() {
lis, err := net.Listen(“tcp”, “:9000”)
if err!= nil {
log.Fatalf(“failed to listen: %v”, err)
}
srv := grpc.NewServer()
pb.RegisterChatServiceServer(srv, &ChatServer{})
log.Println(“gRPC server listening on port 9000”)
srv.Serve(lis)
}
“`

Creating the RPC Client

Create a new folder named rpc-client and initiate an npm project. Then, install the RPC package and create a chat.proto file with the same contents as before.

Create a new file named client.js and implement the client:

“`
const grpc = require(‘@grpc/proto-loader’);
const chatProto = grpc.loadSync(‘chat.proto’, {});
const chatPackage = chatProto.chat;

const client = new chatPackage.ChatService(‘localhost:9000’, grpc.credentials.createInsecure());

client.SayHello({ body: ‘Hello, world!’ }, (err, response) => {
if (err) {
console.error(err);
} else {
console.log(response.body);
}
});

client.GetDetails({ name: ‘John’, age: 30 }, (err, response) => {
if (err) {
console.error(err);
} else {
console.log(response.body);
}
});
“`

Running the Client

Run the client code to make calls to the RPC server:


node client.js

This should return the following output from the server:


SayHello Called
GetDetails Called

Congratulations! You’ve successfully built an RPC server in Go and an RPC client in Node.js.

Leave a Reply

Your email address will not be published. Required fields are marked *