Building a TCP Server and Client with Go's net Package

TCP Server Implementation

package main

import (
	"fmt"
	"net"
)

func handleConnection(conn net.Conn) {
	defer conn.Close()

	for {
		buffer := make([]byte, 512)
		n, readErr := conn.Read(buffer)
		if readErr != nil {
			return
		}

		fmt.Printf("Received data (%d bytes): %v\n", n, buffer[:n])
		fmt.Printf("Decoded message: %s\n", string(buffer[:n]))
	}
}

func main() {
	fmt.Println("Starting TCP server on port 8888...")
	
	listener, err := net.Listen("tcp", "127.0.0.1:8888")
	if err != nil {
		fmt.Printf("Failed to start listener: %v\n", err)
		return
	}

	for {
		clientConn, acceptErr := listener.Accept()
		if acceptErr != nil {
			fmt.Printf("Connection accept failed: %v\n", acceptErr)
			continue
		}
		
		fmt.Printf("New connection established: %s\n", clientConn.RemoteAddr().String())
		go handleConnection(clientConn)
	}
}

TCP Cleint Implementation

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
)

func main() {
	fmt.Println("Initializing client connection...")
	
	conn, dialErr := net.Dial("tcp", "127.0.0.1:8888")
	if dialErr != nil {
		fmt.Printf("Connection failed: %v\n", dialErr)
			return
	}
	fmt.Printf("Connected to server: %v\n", conn.LocalAddr())

	inputReader := bufio.NewReader(os.Stdin)
	fmt.Print("Enter message: ")
	message, readErr := inputReader.ReadString('\n')
	if readErr != nil {
		fmt.Println("Input read error")
		return
	}

	bytesSent, writeErr := conn.Write([]byte(message))
	if writeErr != nil {
		fmt.Printf("Write failed: %v\n", writeErr)
		return
	}

	fmt.Printf("Successfully sent %d bytes\n", bytesSent)
	conn.Close()
}

How It Works

The server uses net.Listen to create a TCP listener on the specified address. The Accept method blocks until a client connects, returning a net.Conn interface representing the connection. Each client connection is handled in a separate goroutine to allow concurrent connections.

Data reception uses a fixed-size byte buffer. The Read method returns both the number of bytes read and any error encountered. When the client disconnects, Read returns an error and the handler function exits.

The client initiates connection with net.Dial, which establishes a TCP handshake with the serverr. After connecting, it reads user input line-by-line using bufio.Reader and sends the data through the connection via Write.

Key Functions

Function Purpose
net.Listen Creates a TCP listener on a network address
Accept Waits for and returns the next incoming connection
Read Reads data from the connection into a byte slice
Write Writes data to the connection
net.Dial Initiates a connection to a remote address

Tags: Go tcp networking concurrent goroutine

Posted on Tue, 30 Jun 2026 17:30:40 +0000 by Z3RatuL