Skip to main content

Featured

Building a gRPC Service with Nested Messages, Repeated Fields, and Oneof in Python

Introduction:  gRPC is a high-performance, open-source framework developed by Google for building efficient and scalable distributed systems. It provides a language-agnostic way to define and implement services using Protocol Buffers (protobuf) as the interface definition language. In this tutorial, we'll explore how to build a gRPC service in Python that incorporates advanced features such as nested messages, repeated fields, and oneof. These features allow us to create complex data structures and handle scenarios where multiple values or mutually exclusive fields are involved.   Prerequisites: Basic understanding of gRPC and Protocol Buffers. Python development environment set up.   Step 1: Define the Protocol Buffers (protobuf) File  Start by defining the service and message definitions in a proto file. Here's an example of a proto file named example.proto that defines a gRPC service with nested messages, repeated fields, and oneof: syntax = "proto3" ; package

Getting Started with WebSockets in Go (Golang Tutorial)

 

## Introduction

WebSockets are a powerful tool for building real-time applications that require bi-directional communication between the server and the client. In this tutorial, we will learn how to use WebSockets in Go with the help of the Gorilla WebSocket package.

## Setting up the server

We will create a simple application that echoes back any message sent by the client. Our application will use the Gin framework, which is a popular web framework in Go. The client-side of our application will be an HTML page that will be served by our application.

First, we will create a new directory for our project and navigate into it using the terminal:

```shell
   mkdir websocket-app
   cd websocket-app
```

Next, we will initialize our Go module using the following command:

```shell
   go mod init websocket-app
```

Now that our Go module is initialized, we can install the Gin framework and Gorilla WebSocket package using the following command:

```shell
   go get -u github.com/gin-gonic/gin
   go get github.com/gorilla/websocket 
```

This command will download and install the latest version of the Gin framework and its dependencies.

Once we have installed the packages, we can create our main.go file and add the necessary code.
package main

import (
  "flag"
  "log"
  "net/http"

  "github.com/gin-gonic/gin"
  "github.com/gorilla/websocket"
)

var (
  certPath string
  keyPath  string
  address  string
)

func init() {
  flag.StringVar(&certPath, "cert", "", "path to SSL/TLS certificate file")
  flag.StringVar(&keyPath, "key", "", "path to SSL/TLS private key file")
  flag.StringVar(&address, "a", ":7000", "address to use")
}

var upgrader = websocket.Upgrader{
  ReadBufferSize:  1024,
  WriteBufferSize: 1024,
  CheckOrigin: func(r *http.Request) bool {
    return true
  },
}

func main() {
  flag.Parse()

  router := gin.Default()

  // Serve HTML page to trigger connection
  router.GET("/", func(c *gin.Context) {
    c.File("index.html")
  })

  // Handle WebSocket connections
  router.GET("/ws", func(c *gin.Context) {
    conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
    if err != nil {
      panic(err)
    }

    for {
      // Read message from client
      messageType, p, err := conn.ReadMessage()
      if err != nil {
        panic(err)
      }

      // Echo message back to client
      err = conn.WriteMessage(messageType, p)
      if err != nil {
        panic(err)
      }
    }
  })

  if certPath == "" || keyPath == "" {
    log.Println("Warning: SSL/TLS certificate and/or private"+ 
                 "key file not provided. Running server unsecured.")
    err := router.Run(address)
    if err != nil {
      panic(err)
    }
  } else {
    err := router.RunTLS(address, certPath, keyPath)
    if err != nil {
      panic(err)
    }
  }
}

In this code, we first import the necessary packages, including `github.com/gorilla/websocket` for WebSocket support and `github.com/gin-gonic/gin` for web framework support.

We then define some variables using the flag package to allow the user to specify the SSL/TLS certificate and private key files and the address to use.

Next, we create an instance of the Gorilla WebSocket Upgrader, which is used to upgrade an HTTP connection to a WebSocket connection.

We then define the main function, where we parse the command-line flags using the flag package and create an instance of the Gin web framework.

We define two routes for our server. The first route ("/") serves an HTML page that triggers the WebSocket connection, and the second route ("/ws") handles the WebSocket connections.

In the "/ws" route, we first upgrade the HTTP connection to a WebSocket connection using the upgrader. We then read messages from the client and echo those messages back to the client using the connection.

Finally, we added a simple HTML page that contains a text input field and a button to send messages to the WebSocket server. The JavaScript code initializes a WebSocket connection to the server and sends messages typed into the input field to the server when the button is clicked. The server then sends the same message back to the client, which is displayed on the web page.
<!DOCTYPE html>
<html>
<head>
  <title>WebSocket Echo Test</title>
</head>
<body>
  <h1>WebSocket Echo Test</h1>
  <input type="text" id="message" placeholder="Type a message...">
  <button onclick="sendMessage()">Send</button>
  <hr>
  <div id="output"></div>

  <script>
    let secure = window.location.protocol.includes('https') ? 's':'';
    var socket = new WebSocket("ws"+secure+"://" + window.location.host + "/ws");
   
    socket.onopen = function(event) {
      console.log("WebSocket connected!");
    }

    socket.onmessage = function(event) {
      console.log("Received message:", event.data);
      document.getElementById("output").innerHTML += event.data + "<br>";
    }

    function sendMessage() {
      var message = document.getElementById("message").value;
      socket.send(message);
      document.getElementById("message").value = "";
      console.log("Sent message:", message);
    }
  </script>
</body>
</html>

The **index.html** file we created above contains the client-side code for our WebSocket application. Let's take a closer look at what it does.

First, we start by including a few basic HTML elements, including a heading and a form for sending messages.

Next, we include a JavaScript block that sets up a WebSocket connection with the server and handles incoming messages.The first line of this script sets a variable called secure to either "s" or an empty string depending on whether the current protocol is HTTPS or not. We use this variable to construct the WebSocket URL later on.

Next, we create a new WebSocket object using the WebSocket constructor. We pass in the URL of our WebSocket endpoint, which is constructed using the current host and the path to our WebSocket handler on the server (/ws in this case). We also include the secure variable we defined earlier to ensure that the correct protocol is used.

Once the WebSocket connection is established, we set up two event handlers: onopen and onmessage. The onopen handler simply logs a message to the console to indicate that the WebSocket connection has been established.

The onmessage handler is more interesting. This handler is called whenever a message is received from the server. When a message is received, we log the message to the console and add it to the #output element on the HTML page.

Finally, we define a function called sendMessage() that is called when the "Send" button is clicked. This function gets the value of the #message input field, sends it to the server using the send() method of the WebSocket object, and clears the input field.

That's it! With this client-side code in place, we can send messages to the server and receive them back in real time using a WebSocket connection.

## Running the code

To test the application, we need to start the server by running the following command in the terminal:
```shel
   go run main.go -a=:7000
```

This command will start the server on port 7000 by default. If you want to use a different port, you can specify it by passing the `-a` flag followed by the desired address and port. If your server has SSL/TLS certivicate you can also passing the flags as `-cert=path_to_SSL/TLS_certificate_file.cert` and `-key=path_to SSL/TLS_private_key_file.privkey`

Once the server is running, open a web browser and navigate to `http://localhost:7000`. You should see the HTML page we created earlier. Type a message into the input field and click the "Send" button. The message should be echoed back to you and displayed on the web page.

Congratulations, you have successfully implemented a simple WebSocket server in Go! With this basic knowledge, you can build more complex WebSocket applications that allow for real-time communication between a server and clients.

 

If you found this tutorial on using WebSockets in Go helpful, please consider visiting or cloning my repository on GitHub. You can find the code for this tutorial and other examples of using WebSockets in Go at the following link: 

```shell
   https://github.com/royyanwibisono/testwebsocket.git
```

By visiting or cloning my repository, you'll be able to explore the code for this tutorial in more depth and see other examples of how to use WebSockets in Go. I hope you find this tutorial useful, and I welcome any feedback or suggestions you may have for improving it. 

 

Thank you for reading! 

Comments