Skip to content

Instantly share code, notes, and snippets.

@dsiddharth
Created April 11, 2024 15:09
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 dsiddharth/0c12f415e2b8ae1328b4a5f828f41ea4 to your computer and use it in GitHub Desktop.
Save dsiddharth/0c12f415e2b8ae1328b4a5f828f41ea4 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"net"
"os"
"sort"
"time"
)
func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "Usage: %s <host:port> <number_of_packets>\n", os.Args[0])
os.Exit(1)
}
serverAddr := os.Args[1]
numPackets := 10 // Default number of packets
fmt.Sscanf(os.Args[2], "%d", &numPackets) // Parse the desired number of packets from command line
addr, err := net.ResolveUDPAddr("udp", serverAddr)
if err != nil {
fmt.Println("Error resolving UDP address:", err)
os.Exit(1)
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
fmt.Println("Error dialing UDP:", err)
os.Exit(1)
}
defer conn.Close()
// Slice to store latencies and a slice to track jitter between packets
latencies := make([]time.Duration, 0, numPackets)
jitters := make([]time.Duration, 0, numPackets-1)
var lastLatency time.Duration
for i := 0; i < numPackets; i++ {
startTime := time.Now()
_, err = conn.Write([]byte("ping"))
if err != nil {
fmt.Println("Error sending data:", err)
continue
}
buffer := make([]byte, 1024)
conn.SetReadDeadline(time.Now().Add(1 * time.Second)) // 1 second timeout for the echo
_, _, err = conn.ReadFrom(buffer)
if err != nil {
fmt.Println("Error reading from server:", err)
continue
}
endTime := time.Now()
latency := endTime.Sub(startTime)
latencies = append(latencies, latency)
// Calculate and store jitter
if i > 0 {
jitter := latency - lastLatency
if jitter < 0 {
jitter = -jitter
}
jitters = append(jitters, jitter)
}
lastLatency = latency
fmt.Printf("Packet %d RTT: %v\n", i+1, latency)
}
// Sort latencies to calculate percentiles
sort.Slice(latencies, func(i, j int) bool {
return latencies[i] < latencies[j]
})
minLatency := latencies[0]
maxLatency := latencies[len(latencies)-1]
p50 := latencies[len(latencies)*50/100]
p95 := latencies[len(latencies)*95/100]
p99 := latencies[len(latencies)*99/100]
// Calculate average jitter
var totalJitter time.Duration
for _, jitter := range jitters {
totalJitter += jitter
}
averageJitter := totalJitter / time.Duration(len(jitters))
fmt.Printf("Min RTT: %v\n", minLatency)
fmt.Printf("P50 RTT: %v\n", p50)
fmt.Printf("P95 RTT: %v\n", p95)
fmt.Printf("P99 RTT: %v\n", p99)
fmt.Printf("Max RTT: %v\n", maxLatency)
fmt.Printf("Average Jitter: %v\n", averageJitter)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment