Skip to content

Instantly share code, notes, and snippets.

@YangKeao
Created February 5, 2025 13:28
Show Gist options
  • Save YangKeao/8aa7f4bc79387ab80d690ed59a39724e to your computer and use it in GitHub Desktop.
Save YangKeao/8aa7f4bc79387ab80d690ed59a39724e to your computer and use it in GitHub Desktop.
A demo shows that Linux will attach `FIN` flag to the last packet in the queue, which will cause `PSH, FIN` in the same packet.
package main
import (
"bufio"
"fmt"
"log"
"net"
"os"
"strings"
"time"
)
const (
PORT = 8080
BUFFER_SIZE = 1024
)
func runServer() {
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", PORT))
if err != nil {
log.Fatalf("Failed to create socket: %v", err)
}
defer listener.Close()
fmt.Printf("Server listening on port %d...\n", PORT)
conn, err := listener.Accept()
if err != nil {
log.Fatalf("Accept failed: %v", err)
}
defer conn.Close()
message := []byte(strings.Repeat("A", BUFFER_SIZE))
start := time.Now()
for time.Since(start) < time.Second*5 {
bytesWritten, err := conn.Write(message)
if err != nil {
break
}
fmt.Printf("Write: %d\n", bytesWritten)
}
fmt.Println("Server sent all data and closed immediately")
}
func runClient() {
var conn net.Conn
var err error
// Retry connection with timeout
for {
conn, err = net.Dial("tcp", "127.0.0.1:8080")
if err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
defer conn.Close()
reader := bufio.NewReader(conn)
totalReceived := 0
for {
buffer := make([]byte, BUFFER_SIZE)
bytesRead, err := reader.Read(buffer)
if err != nil {
break
}
totalReceived += bytesRead
fmt.Printf("Received %d bytes: %s\n", bytesRead, string(buffer[:bytesRead]))
}
fmt.Println("Server closed connection")
}
func main() {
if len(os.Args) != 2 {
log.Fatalf("Usage: %s [server|client]", os.Args[0])
}
switch strings.ToLower(os.Args[1]) {
case "server":
runServer()
case "client":
runClient()
default:
log.Fatal("Invalid argument - must be 'server' or 'client'")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment