Sling Academy
Home/Golang/Creating Custom Protocols with Go's `net` Package

Creating Custom Protocols with Go's `net` Package

Last updated: November 27, 2024

In this article, you will learn how to create custom protocols using Go's net package. Custom protocols can be useful when you need specialized communication rules not covered by standard protocols like HTTP or TCP.

Understanding the Basics of Go's net Package

The net package in Go provides a portable interface for network I/O, including TCP/IP, UDP, domain name system (DNS) name resolution, and more. It’s a versatile package that lets you build network applications efficiently.

Setting Up a Simple Go Project

Before diving into custom protocol creation, ensure that Go is installed on your system. You can verify this by opening your terminal and running:

go version

Once Go is set up, create a new directory for your project and initialize a new Go module:

mkdir custom-protocol
cd custom-protocol
go mod init custom-protocol

Creating a Simple TCP Server

Let's start by creating a basic TCP server. This will serve as a foundation upon which to build your custom protocol.

package main

import (
	"fmt"
	"net"
)

func main() {
	ln, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(err)
	}
	defer ln.Close()

	fmt.Println("Server is listening on port 8080...")

	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println(err)
			continue
		}
		go handleConnection(conn)
	}
}

func handleConnection(conn net.Conn) {
	defer conn.Close()
	
	fmt.Fprintf(conn, "Welcome to our server!\n")
}

This script sets up a TCP server listening on port 8080 that responds with a welcome message for each new connection.

Implementing a Custom Protocol

To implement a custom protocol, you can establish specific rules for data formatting and communication between client and server. For example, consider a simple key-value protocol.

Defining the Protocol Rules

  • A message starts with the command keyword 'SET' or 'GET'.
  • For 'SET', a key-value pair follows the command.
  • For 'GET', a key for which the value is needed.
  • Responses contain status or fetched value.

Server-Side Implementation

Here is how you can write server-side logic to handle this protocol:

package main

import (
	"bufio"
	"fmt"
	"net"
	"strings"
)

var store = make(map[string]string)

func main() {
	ln, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(err)
	}
	defer ln.Close()

	fmt.Println("Server is listening on port 8080...")

	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println(err)
			continue
		}
		go handleConnection(conn)
	}
}

func handleConnection(conn net.Conn) {
	defer conn.Close()
	for {
		netData, err := bufio.NewReader(conn).ReadString('\n')
		if err != nil {
			fmt.Println(err)
			return
		}

		message := strings.TrimSpace(string(netData))

		parts := strings.SplitN(message, " ", 2)
		command := parts[0]
		data := ""
		if len(parts) > 1 {
			data = parts[1]
		}

		response := ""
		switch command {
		case "SET":
			kv := strings.SplitN(data, " ", 2)
			if len(kv) != 2 {
				response = "Error: Invalid SET command\n"
			} else {
				key := kv[0]
				value := kv[1]
				store[key] = value
				response = "OK\n"
			}
		case "GET":
			value, found := store[data]
			if found {
				response = fmt.Sprintf("%s\n", value)
			} else {
				response = "Error: Key not found\n"
			}
		default:
			response = "Error: Unknown command\n"
		}

		conn.Write([]byte(response))
	}
}

Testing Your Custom Protocol

To test your setup, you can use telnet or netcat as a client to manually send SET and GET commands.

# Start the server in the terminal
go run main.go

# In another terminal, you can use telnet or netcat
telnet localhost 8080
# or
nc localhost 8080

# Once connected, you can enter commands like:
SET name John Doe
GET name

Conclusion

This guide has shown you how to create a custom protocol in Go using the net package. Developing custom protocols can be an excellent way to establish unique communication schemes suitable for specific application requirements.

Next Article: Networking Best Practices for Go Applications

Previous Article: Working with UDP and TCP Sockets in Go

Series: Networking and Server

Golang

Related Articles

You May Also Like

  • How to remove HTML tags in a string in Go
  • How to remove special characters in a string in Go
  • How to remove consecutive whitespace in a string in Go
  • How to count words and characters in a string in Go
  • Relative imports in Go: Tutorial & Examples
  • How to run Python code with Go
  • How to generate slug from title in Go
  • How to create an XML sitemap in Go
  • How to redirect in Go (301, 302, etc)
  • Using Go with MongoDB: CRUD example
  • Auto deploy Go apps with CI/ CD and GitHub Actions
  • Fixing Go error: method redeclared with different receiver type
  • Fixing Go error: copy argument must have slice type
  • Fixing Go error: attempted to use nil slice
  • Fixing Go error: assignment to constant variable
  • Fixing Go error: cannot compare X (type Y) with Z (type W)
  • Fixing Go error: method has pointer receiver, not called with pointer
  • Fixing Go error: assignment mismatch: X variables but Y values
  • Fixing Go error: array index must be non-negative integer constant