How to Create TCP Client and Server Using Golang [Step by Step Guide]

How to Create TCP Client and Server Using Golang [Step by Step Guide]

In this tutorial, we will learn about “How to create TCP client and server using Golang using step by step guide”. The client-server architecture basically provides a flexible and scalable model for building distributed systems where clients and servers collaborate to achieve various tasks and provide services to end-users. It’s a foundational concept in modern computing, powering a wide range of applications and services on the internet and enterprise networks. We will learn more about client-server architecture and implement the same in Golang. So, let us begin the tutorial.

 

What is Client-Server Architecture

Client-server architecture is a computing model where tasks or workloads are divided between service requesters (clients) and service providers (servers). It’s a fundamental model in networked systems where clients initiate requests for resources or services, and servers respond to those requests by providing the requested resources or services.

Here are the key components and characteristics of client-server architecture:

  1. Clients: Clients are devices or software applications that request services or resources from servers. Clients initiate communication by sending requests to servers. Examples of clients include web browsers, mobile apps, desktop applications, etc.
  2. Servers: Servers are devices or software applications that provide services or resources to clients. Servers listen for incoming requests from clients, process those requests, and send back responses. Examples of servers include web servers, database servers, email servers, etc.
  3. Communication: Communication between clients and servers typically occurs over a network using various communication protocols such as HTTP, HTTPS, TCP/IP, etc. Clients send requests to servers, and servers respond to those requests with the requested data or services.
  4. Request-Response Model: Client-server architecture follows a request-response model, where clients send requests to servers, and servers respond to those requests with the requested data or services. This model allows for efficient distribution of workloads and resources.
  5. Scalability: Client-server architecture allows for scalable systems where multiple clients can communicate with multiple servers simultaneously. This scalability enables systems to handle increasing workloads by distributing tasks across multiple servers.
  6. Centralized Services: Servers in client-server architecture often provide centralized services, such as databases, file storage, authentication, etc. Clients access these centralized services by sending requests to the appropriate servers.
  7. Decoupling of Presentation and Data Processing: In many client-server applications, the presentation layer (client-side) is decoupled from the data processing layer (server-side). This separation of concerns allows for better maintainability, scalability, and flexibility in software development.

 

How to Create TCP Client and Server Using Golang [Step by Step Guide]

Also Read: How to Implement Stack in Golang [Step by Step Guide]

In Go, you can create TCP client and server applications using the “net “ package, which provides support for various networking protocols, including TCP. There are different packages available to create TCP Client and Server in Golang. These are mentioned below.

  1. Using net.Listen and net.Dial: This is the simplest way to create a TCP server and client. The server listens for incoming connections using net.Listen, and the client connects to the server using net.Dial.
  2. Using net.TCPListener and net.TCPConn: You can also create TCP servers and clients using net.TCPListener and net.TCPConn types, which provide more control over TCP-specific options and behaviors.
  3. Using Libraries: There are also third-party libraries and frameworks available in Go for building TCP servers and clients, such as github.com/golang/net, github.com/hashicorp/yamux, etc. These libraries may offer additional features and functionalities beyond the standard net package.

For the sake of this tutorial, we will use “net” package to write the client-server code. In our example, we have created a client which will send array of strings to the server. Our server in return will reverse these strings and return back the output to the client.

Below, I have provided the code of both a TCP server and a TCP client. The examples provided below demonstrate the first method using the standard net package. Depending on your requirements and use case, you can choose the approach that best fits your needs.

Prerequisites

  • Go software installed
  • VS Code IDE (or any other Go IDE)
  • Basic understanding on Go 

 

Create TCP Client File (tcpClient.go)

This Go code defines a function SendAndReceiveMessages responsible for sending messages to a server and printing the reversed response. this function facilitates communication between a client and a server over TCP, sending messages and printing the reversed responses. Create a new file and save below code. I have saved it in tcpClient.go file.

/* This file will handle the client-side logic, sending messages to the server*/
package main
import (

    "bufio"
    "fmt"
    "net"
)

// Sends each message from the array to the server and prints the reversed response
func SendAndReceiveMessages(messages []string, port string) {

    for _, message := range messages {
        conn, err := net.Dial("tcp", "localhost:"+port)

        if err != nil {
            fmt.Println("Error connecting to the server: ", err)
            return
        }

        //Send message to the server
        conn.Write([]byte(message + "\n"))

        //Receive and print the response from the server
        response, err := bufio.NewReader(conn).ReadString('\n')

        if err != nil {
            fmt.Println("Error reading the response: ", err)
            return
        }

        fmt.Printf("Original: %s, Reversed: %s", message, response)
        defer conn.Close()
    }
}

 

Create TCP Server File (tcpServer.go)

This Go code defines a simple TCP server that listens for incoming connections on a specified port. When a client connects to the server, the server reads messages from the client, reverses them, and sends the reversed message back to the client. this code sets up a simple TCP server that demonstrates how to handle client connections, read and write data over the network, and manipulate strings. Create a new file and save below code. I have saved it in tcpServer.go file.
package main
import (

    "bufio"
    "fmt"
    "net"
)

func handleClient(conn net.Conn) {

    defer conn.Close()
    scanner := bufio.NewScanner(conn)

    for scanner.Scan() {

        //Reverse the received message
        message := scanner.Text()
        reversedMessage := reverseString(message)

        //Send the reversed string back to the client
        conn.Write([]byte(reversedMessage + "\n"))
    }
}

func reverseString(message string) string {

    runes := []rune(message)
    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
        runes[i], runes[j] = runes[j], runes[i]
    }
    return string(runes)
}

func StartServer(port string) {

    listener, err := net.Listen("tcp", "localhost:"+port)
    if err != nil {
        fmt.Println("Error starting the server: ", err)
        return
    }

    defer listener.Close()
    fmt.Println("Server started. Listening on Port: ", port)

    for {

        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("Error accepting the connection: ", err)
            continue
        }
        go handleClient(conn)
    }
}

 

Create main.go File (main.go)

This Go code appears to be the main entry point for a program that orchestrates the client and server logic. this code sets up a scenario where a server is started in a separate goroutine, and then the main function waits briefly before initiating client communication with the server. Create a new file and save below code. I have saved it in main.go file.
/* This file contains the main function and orchestrate the client and server logic */
package main
import (
    "time"
)

func main() {

    //Start the server in a goroutine
    go StartServer("4040")

    //Wait fot sometime to ensure server has started
    <-time.After(time.Second * 2)
    message := []string{"Linux", "Nasa"}
    SendAndReceiveMessages(message, "4040")
}

 

Create go.mod File

Next, create a mod file for the current project using the command go mod init <path> as shown below.

[email protected]/client-server$ go mod init clientServer

 

Execute the Code

When you have completed the creation of all the above code, next job is to execute the code and validate the output. Build the code using below command go build <go-file-path>.  In our case, the go file path is the current directory so we will use "." to denote the command to pick all the .go files from current folder.
[email protected]/client-server$ go build .

 

Above command will generate a binary file in the current folder as shown in snip below.

 

Next, execute the binary to get the output as shown below. As you see, first the Server is started and listening on port 4040. It then received the input from client and returned the output.
[email protected]/client-server$ .\clientServer.exe
Server started. Listening on Port: 4040
Original: Linux, Reversed: xuniL
Original: Nasa, Reversed: asaN

 

Summary

This step-by-step guide provides a comprehensive overview of creating TCP client and server applications using the Go programming language. From establishing connections to handling data exchange, readers will learn the fundamentals of TCP communication in Go, empowering them to build robust and efficient networked applications.

 

Leave a Comment