TCP Line-Protocol Echo

A complete TCP server and client in one program. The server accepts a connection, reads newline-delimited lines with bufio.Scanner, and echoes each one uppercased. The client dials, sends two lines, and reads the replies.

package main

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

func main() {
	ln, err := net.Listen("tcp", "127.0.0.1:0") // :0 lets the OS pick a free port
	if err != nil {
		fmt.Println("listen:", err)
		return
	}
	defer ln.Close()
	fmt.Println("listening on", ln.Addr())

	// Server: one goroutine per connection, line-delimited framing.
	go func() {
		conn, err := ln.Accept()
		if err != nil {
			return
		}
		defer conn.Close()
		sc := bufio.NewScanner(conn)
		for sc.Scan() {
			fmt.Fprintf(conn, "%s\n", strings.ToUpper(sc.Text()))
		}
	}()

	// Client: dial, send two lines, read the echoes.
	conn, err := net.Dial("tcp", ln.Addr().String())
	if err != nil {
		fmt.Println("dial:", err)
		return
	}
	defer conn.Close()

	fmt.Fprintln(conn, "hello")
	fmt.Fprintln(conn, "sockets")
	r := bufio.NewReader(conn)
	for i := 0; i < 2; i++ {
		reply, _ := r.ReadString('\n')
		fmt.Print("server replied: ", reply)
	}
	// server replied: HELLO
	// server replied: SOCKETS
}

Save the code as main.go and run it:

go run main.go

Expected output:

listening on 127.0.0.1:54100
server replied: HELLO
server replied: SOCKETS

The port is chosen by the OS (:0), so it will differ each run.

💻 Run locally

Copy the code above and run it on your machine

© 2026 ByteLearn.dev. Free courses for developers. · Privacy