Skip to content

Instantly share code, notes, and snippets.

@jpittis
Created January 2, 2019 13:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpittis/4357d817dc425ae99fbf719828ab1800 to your computer and use it in GitHub Desktop.
Save jpittis/4357d817dc425ae99fbf719828ab1800 to your computer and use it in GitHub Desktop.
FIN vs RST Experiment
package main
import (
"log"
"net"
"os"
"time"
)
// FIN vs RST Experiment
// ---
// Demonstrates how to trigger a connection reset by peer on close
// using SetLinger.
// ---
// $ go run experiment.go
// 2019/01/02 08:29:36 connect err: EOF
// exit status 1
// $ go run experiment.go rst
// 2019/01/02 08:29:40 connect err: read tcp 127.0.0.1:50361->127.0.0.1:4444: read: connection reset by peer
// exit status 1
func main() {
rst := len(os.Args) >= 2 && os.Args[1] == "rst"
// Start a listener that accepts one connection and then immediately closes it.
go func() {
err := listen(rst)
if err != nil {
log.Fatalf("listen err: %s", err)
}
}()
// Wait for listener to start.
time.Sleep(time.Second)
// Connect and report error on close.
err := connect()
if err != nil {
log.Fatalf("connect err: %s", err)
}
}
func listen(rst bool) error {
ln, err := net.Listen("tcp", "localhost:4444")
if err != nil {
return err
}
// Accept one connection.
conn, err := ln.Accept()
if err != nil {
return err
}
// Force an RST if flag is set.
// Close with normal FIN if flag is not set.
if rst {
tcpConn := conn.(*net.TCPConn)
tcpConn.SetLinger(0)
}
return conn.Close()
}
func connect() error {
conn, err := net.Dial("tcp", "localhost:4444")
if err != nil {
return err
}
// Block until close.
buf := make([]byte, 1)
_, err = conn.Read(buf)
return err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment