Implementing a TCP Client and Server in Go: A Ping Pong Example

July 30, 2023

Go, also known as Golang, is a statically typed, compiled language known for its simplicity and efficiency. It's a great language for writing networking applications, and in this blog post, we'll walk through creating a simple TCP client and server that play a game of "ping-pong".

TCP Server

Let's start by creating our TCP server. The server will listen for incoming connections, read incoming messages, and respond accordingly.
package main
import (
	"bufio"
	"fmt"
	"net"
	"strings"
)
func main() {
	fmt.Println("Starting server...")
	// Listen on TCP port 8080 on all available unicast and
	// anycast IP addresses of the local system.
	ln, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(err)
	}
	defer ln.Close()
	for {
		// Wait for a connection.
		conn, err := ln.Accept()
		if err != nil {
			panic(err)
		}
		// Handle the connection in a new goroutine.
		go handleConnection(conn)
	}
}
func handleConnection(conn net.Conn) {
	defer conn.Close()
	// Create a new reader and read the incoming message.
	reader := bufio.NewReader(conn)
	msg, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println("Failed to read from client:", err)
		return
	}
	msg = strings.TrimSpace(msg)
	fmt.Println("Received:", msg)
	// If the message is "ping", respond with "pong".
	if msg == "ping" {
		fmt.Println("Sending: pong")
		conn.Write([]byte("pong\n"))
	}
}
In this code, we first create a listener on port 8080. We then enter a loop where we accept incoming connections and handle them in separate goroutines. This allows our server to handle multiple connections concurrently.
 
The `handleConnection` function reads a message from the client. If the message is "ping", it responds with "pong".

TCP Client

Next, let's create our TCP client. The client will connect to the server, send a message, and print out the server's response.
 
package main
import (
	"bufio"
	"fmt"
	"net"
)
func main() {
	fmt.Println("Starting client...")
	// Connect to the server.
	conn, err := net.Dial("tcp", "localhost:8080")
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	// Send a message to the server.
	fmt.Println("Sending: ping")
	conn.Write([]byte("ping\n"))
	// Wait for a response.
	reader := bufio.NewReader(conn)
	msg, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println("Failed to read from server:", err)
		return
	}
	fmt.Println("Received:", strings.TrimSpace(msg))
}
In this code, we connect to the server and send the message "ping". We then wait for a response and print it out.

Running the Example

To run this example, start the server in one terminal window and the client in another. You should see the client send "ping" and the server respond with "pong".
 
This is a simple example, but it demonstrates the basics of creating a TCP client and server in Go. From here, you can expand on this example to create more complex networking applications.

Read also

Golang transfer a file over a TCP socket
Generate CRC32 hash of a file in Golang turorial
Generate SHA1 hash of a file in Golang example
Generate MD5 hash of a file in Golang
Golang human readable byte sizes
Golang creating a worker thread pool using maps
Comments
Tags