WTF is Grpc? Part 3: Real time Chat ft. Flutter and Golang

djsmk123

Md. Mobin

Posted on October 27, 2023

WTF is Grpc? Part 3: Real time Chat ft. Flutter and Golang

Welcome back, dear readers, to the world of "Wtf is gRPC?" – where we turn tech into a comedy show! πŸš€

In Part 3, we're diving into real-time chat with the grace of caffeine-fueled squirrels and the humor of rubber chickens at a stand-up gig!

Get ready to leave slow chats in the dust and make your app as snappy as a squirrel on roller skates. Grab your code editor, sense of humor, and let's chat it up in style. Part 3 is gonna be chat-tastic! πŸ°πŸ’¬πŸ˜„

grpc-socket-meme

Table of Contents: Part 3 - Real-Time Chat Extravaganza πŸŽ‰

Introduction to gRPC Bi-directional: The Magic of Two-Way Chats

As we've journeyed through gRPC, we first delved into unary communication, which is essentially one-way communication from the client to the server. Then, we ventured into the world of server-side streaming.

Now, let's dive into gRPC Bi-directional communication. This is where things get really interesting! In Bi-directional streaming RPC, both the client and server engage in a lively conversation by sending a continuous stream of messages back and forth.

Here's how it works:

  • The client initiates the action by setting up an HTTP stream with some initial header frames.
  • Once this connection is established, both the client and the server can send messages simultaneously, without waiting for the other party to finish. It's like a dynamic chat where no one has to take turns.

Think of gRPC as the superhero chat line. It's like Tony's suit and Bruce's lab assistant, J.A.R.V.I.S., having a direct line to each other.

Socket vs. gRPC Bi-directional: A Cinematic Showdown" 🍿πŸŽ₯

Aspect Socket gRPC Bi-directional Top-Rated Movie Comparison
Setup Complexity Generally low, traditional sockets require less setup Requires setting up gRPC services and protocols, which can be more complex Like the simplicity of "The Shawshank Redemption"
Communication Type Low-level and can be used for any data format High-level, designed for structured data transmission Similar to the plot intricacies of "The Godfather"
Performance Can be efficient for simple data exchange Optimized for high-performance, especially in microservices Like the action-packed "Mad Max: Fury Road"
Bi-directional Possible with added complexity and custom handling Inherently supports efficient bi-directional communication Much like "Pulp Fiction's" non-linear storytelling
Error Handling Requires custom error handling Provides built-in status codes and error handling Comparable to the suspense in "The Silence of the Lambs"
Cross-Language Supports multiple programming languages Multi-language support with protocol buffers Like the multilingual charm of "Inglourious Basterds"
Integration Ease Requires more manual integration Easier integration into gRPC-compatible systems Much like the seamless blend in "The Dark Knight"

grpc bi-directional

Setup Your Server: Where the Real-Time Chat Spells Begin

  • Let's continue code from part 2,where we left.


git clone git@github.com:Djsmk123/Wtf-is-grpc.git


Enter fullscreen mode Exit fullscreen mode
  • Switch to part-2 branch(for starter code) ```

git switch part2

- As we are going to create Chat one to one service for that we required to get all the users and then communicate.

- Create profobuf for getting users(`rpc_users.proto`)

  • Add GetUsers rpc service in GRPCServerService
Enter fullscreen mode Exit fullscreen mode

// add this line to import
import "rpc_users.proto";

service GrpcServerService {
// add this line too
rpc GetUsers(UsersListRequest) returns (ListUserMessage) {};
}


- Generate equivalent code for server(`Golang`)

Enter fullscreen mode Exit fullscreen mode

protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
--go-grpc_out=pb --go-grpc_opt=paths=source_relative \
proto/*.proto


- Add function in `auth` package `get_users.go`


  • Let's call this function in grpc-server interface(package gapi) and add this function in auth.go.
  • We are done with this. But we required users so that we can send message so don't, I am providing list of users (around 35), just load them into mongodb.

users-data.json

> Note: Password for each user is 12345678.

Setting Up Your Chat Service:

Establishing a chat service is a straightforward procedure.

  • RPC Service Creation : Creating an RPC (Remote Procedure Call) service is at the core of this setup.
  • Bidirectional Message Stream: Implement a bidirectional stream of messages.Messages are initiated by the client and sent to the server.
  • Bidirectional Response Stream: Create a bidirectional stream for responses.Responses are generated by the server and sent back to the client.
  • Acknowledgment Mechanism: Before actual communication begins, an acknowledgment mechanism is necessary to connect both the client and the server.This mechanism helps ensure a successful connection.
  • Database Handling: Notably, the acknowledgment message is designed to be transient and is not stored in the database.
  • Confirmation of Connection: The acknowledgment message serves as a confirmation of a successful connection.

  • Setting up protos: Setup proto for Sending message and get messages

  • Add these rpc function into service
Enter fullscreen mode Exit fullscreen mode

service GrpcServerService {
//add these lines
rpc SendMessage(stream SendMessageRequest) returns (stream Message){};
rpc GetAllMessage(GetAllMessagesRequest) returns (GetAllMessagesResponse){};
}

- Generate equivalent code

Enter fullscreen mode Exit fullscreen mode

protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
--go-grpc_out=pb --go-grpc_opt=paths=source_relative \
proto/*.proto


- We need JWT-based authentication for both receiving and sending messages. While there are two types of interceptors available, namely `unary interceptors` and `stream interceptors`, we currently utilize the `unary interceptor` as our middleware and lets add middleware for stream service too.

![user-auth](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uze08vugtzoi7h5mkqw2.jpg)

- update `middleware.go` in `gapi` package.

  • Register middleware in main.go
Enter fullscreen mode Exit fullscreen mode

//update this line
grpcServer := grpc.NewServer(
grpc.UnaryInterceptor(server.UnaryAuthInterceptor),
grpc.StreamInterceptor(server.StreamAuthInterceptor),
)


- Now create `Message` Object for `mongodb` collection

  • Update MongoCollection
Enter fullscreen mode Exit fullscreen mode

type MongoCollections struct {
Users *mongo.Collection
Chats *mongo.Collection
}


- Before going to into complex part to listen message and store them into db, lets deal with simple rpc function `GetAllMessage` from db and `SendMessage` to store the message.

  • Now we are going to use go-routine to listen and send message to the client

> We are using goroutines and channels to listen for changes in the database. If you want to learn more about goroutines, you can read this blog

  • Let's Define SendMessage and GetAllMesasge for grpc server interface.

> Note: To make connection b/w two users, its required to send first message Join_room so that other user can get acknowledgment.

Testing gRPC in CLI

grpc-testing

Start with Flutter Application: Embark on Your Chatting Adventure

  • Add following dependency into your project:
Enter fullscreen mode Exit fullscreen mode

flutter pub add intl



- Generate equivalent code for dart from `protos`.

Enter fullscreen mode Exit fullscreen mode

protoc --proto_path=proto --dart_out=grpc:lib/pb proto/*.proto


- As it is known issue dart does not generate code `google/protobuf/timestamp.pb.dart`,[read here](https://github.com/google/protobuf.dart/issues/483). So download this file [google_timestamp.pb.dart](https://gist.github.com/Djsmk123/83025e60cbf2c5a931ffefdf2b3a5b7e) and update the generated code as required(just change import path)

- Before starting chat service we need to display all the users into home screen so that we can send message to other users

> PS: I am not going to talk about basic UI building for showing the list of users.

- Add function to get all users in `AuthService` class

Enter fullscreen mode Exit fullscreen mode

class AuthServices{
//keep same, add this function
static Future> getUsers(
{int pageNumber = 1, String? search}) async {
final res = await GrpcService.client.getUsers(
UsersListRequest(pageSize: 10, pageNumber: pageNumber, name: search),
options: CallOptions(metadata: {'authorization': 'bearer $authToken'}));
return res.users.map((e) => UserModel(e.id, e.username, e.name)).toList();
}
}

- Call this function in `HomeScreen()`,for reference use [this ui](https://gist.github.com/Djsmk123/3c39818c3a00c0b01ad8eadb36486102) or create your own.

- Let's Create chat service to get messages(History)

Enter fullscreen mode Exit fullscreen mode

class ChatService {
static Future> getMessages(String username) async {
final res = await GrpcService.client.getAllMessage(
GetAllMessagesRequest(
reciever: username,
),
options: CallOptions(
metadata: {'authorization': 'bearer ${AuthService.authToken}'}));
return res.messages;
}
}


- Let's listen for messages,send message and fetch history.

> Note: UI component maybe missing or you create your own. for reference check source code

  • Let's talk about what we did in above class.
    • In initState() we are starting to listen message by sending first message Join_room to make connection and another function fetchChatsHistory() as name suggested, getting earlier messages by calling grpc unary service.
    • on sending message we are adding message data to stream-controller to send stream of message to the server.

Outputs: The Hilarious Messages of Success

End of the series

Thank you to everyone who has supported me throughout this series. I promise to be more consistent next time. The blog series titled 'Wtf is gRPC?' comes to an end with this post. In Part 1, we delved into authentication and authorization using unary gRPC communication. In Part 2, we had some fun creating a custom notification service in Flutter, along with server-side streaming gRPC. And now, in the grand finale, Part 3, we explored bi-directional gRPC to create a simple real-time chat application. Thanks again, and remember, gRPC isn't as mysterious as it sounds – it's just a protocol! Stay tuned for more tech adventures!

Thank for 2k+ Followers on dev.to

Thanks You

flutter meme

Source code :

Github Repo

Follow me on

Enter fullscreen mode Exit fullscreen mode
πŸ’– πŸ’ͺ πŸ™… 🚩
djsmk123
Md. Mobin

Posted on October 27, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related