golang

Golang TCP Server

In this guide, we will learn how to create a simple TCP server that accepts incoming connections to the server. The server will respond with a message and the current data and time.

This is a good tutorial for beginners who want to get familiar with the Go net package and how to handle requests.

Getting Started

Although the tutorial is very beginner friendly, we recommend having the basics of working with the Go language at hand.

Understanding how to work with Go packages is also very beneficial.

Golang Net Package

The net package is part of the Go standard library. It is used to deliver portable interface for working with network I/O operations. This includes TCP/IP, UDP, DNS, and Unix Domain Sockets.

We will use this package to create a TCP Server.

Building a Simple TCP Server

Let us now get into the code and learn how to build a TCP server. Start by creating a Go file to write your code:

mkdir tcp-server
touch server.go

Edit the file with your text editor of choice and enter the lines below:

package main
import (
    "fmt"
    "net"
    "os"
)

The above lines define the package as a standalone package and imports the required packages.

The next step is to define the parameters for our server. We can define these as global variables as:

const (
    HOST = "localhost"
    PORT = "9001"
    TYPE = "tcp"
)

The next step is to listen for incoming connections. We can do this using the net.Listen method. The function’s syntax is as shown:

func Listen(network, address string) (Listener, error)

It takes the connection type (such as tcp, tcp4, tcp6, unix, or unixpacket), the host, and the connection port. The function will return a listen connection on the specified address.

An example code is as shown:

listen, err := net.Listen(TYPE, HOST+":"+PORT)
if err != nil {
    log.Fatal(err)
    os.Exit(1)
}

We check if the listener encounters any errors, if true, it logs the error message and exists with a status code of 1.

We also need to close the listener after the server terminates. We can do this using the defer keyword and the Close method

listen.Close()

The next step is to continuously listen for connections. We can do this using a for loop as:

for {
    conn, err := listen.Accept()
    if err != nil {
        log.Fatal(err)
        os.Exit(1)
} // handle incoming connections

To handle any incoming requests, we can create a function as:

func handleIncomingRequest(conn net.Conn) {
    // store incoming data
    buffer := make([]byte, 1024)
    _, err := conn.Read(buffer)
    if err != nil {
        log.Fatal(err)
    }
    // respond
    time := time.Now().Format("Monday, 02-Jan-06 15:04:05 MST")
    conn.Write([]byte("Hi back!"))
    conn.Write([]byte(time))
    // close conn
    conn.Close()
}

In the example above, we define a function that takes conn of type net.Conn struct as the parameter.

We then define a new buffer to store the incoming data of size 1024. The next block reads the current time using the time.Now() package.

Using the Write method, we can write the time and a string to the client. Finally, we set the conn.Close() to close the connection.

The full source code is as shown:

package main
import (
    "log"
    "net"
    "os"
    "time"
)

const (
    HOST = "localhost"
    PORT = "9001"
    TYPE = "TCP"
)

func main() {
    listen, err := net.Listen(TYPE, HOST+":"+PORT)
    if err != nil {
        log.Fatal(err)
        os.Exit(1)
    }
    // close listener
    defer listen.Close()
    for {
        conn, err := listen.Accept()
        if err != nil {
            log.Fatal(err)
            os.Exit(1)
        }
        go handleIncomingRequest(conn)
    }
}
func handleIncomingRequest(conn net.Conn) {
    // store incoming data
    buffer := make([]byte, 1024)
    _, err := conn.Read(buffer)
    if err != nil {
        log.Fatal(err)
    }
    // respond
    time := time.Now().Format("Monday, 02-Jan-06 15:04:05 MST")
    conn.Write([]byte("Hi back!\n"))
    conn.Write([]byte(time))

    // close conn
    conn.Close()
}

Compile & Run Server

Once completed, save the file and run the command below to compile the listener into a binary:

go build server.go

Next, run the server as:

./server.exe

The above command should run the TCP server and we can make connections to it.

Testing the TCP Server

To test the TCP server, you can use netcat using the command:

nc localhost 9001

Next, send a message as:

Hi!

The server should respond with a Hi back and the current date and time.

Hi back!
Tuesday, 01-Feb-22 18:03:56 EAT

Conclusion

And with that, we have concluded our tutorial. This guide introduces you to the basics of working with net package by creating a TCP server.

Thanks for reading!

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list