Measuring Network Connection Latency via Port Connectivity Testing Using Native Linux Tools


3 views

When building monitoring systems like Graphite/Diamond collectors, accurately measuring the time required to establish a TCP connection to a remote port is a common requirement. While telnet is often the first tool that comes to mind, its interactive nature makes it suboptimal for scripting.

Linux provides several built-in alternatives that offer better scriptability than telnet:

# Using timeout + bash's special $SECONDS variable
SECONDS=0
timeout 5 bash -c "echo > /dev/tcp/host.example.com/1234"
echo "Connection time: ${SECONDS}s"

# Using nc (netcat) with timeout
time nc -w 5 -zv host.example.com 1234

Bash's built-in /dev/tcp device provides the cleanest solution:

#!/bin/bash
host="example.com"
port="1234"

start_time=$(date +%s%N)
timeout 5 bash -c "exec 3<>/dev/tcp/${host}/${port}" 2>/dev/null
exit_code=$?
end_time=$(date +%s%N)

if [ $exit_code -eq 0 ]; then
  latency=$(( (end_time - start_time) / 1000000 ))
  echo "Connection established in ${latency}ms"
else
  echo "Connection failed or timed out"
fi

For more comprehensive monitoring, consider these approaches:

# Multiple connection attempts with statistics
attempts=5
results=()
for i in $(seq 1 $attempts); do
  start=$(date +%s%N)
  timeout 1 bash -c "exec 3<>/dev/tcp/${host}/${port}" 2>/dev/null
  [ $? -eq 0 ] && results+=($(( ($(date +%s%N) - start) / 1000000 )))
done

# Calculate statistics
printf '%s\n' "${results[@]}" | awk '{sum+=$1; sumsq+=$1*$1} END {
  printf "Avg: %.2fms | Min: %dms | Max: %dms | StdDev: %.2fms\n",
  sum/NR, min, max, sqrt(sumsq/NR - (sum/NR)**2)
}'

When /dev/tcp isn't available, consider these alternatives:

# Using Python
python3 -c "import socket, time; s = socket.socket(); start = time.time(); s.connect(('host', port)); print(f'{(time.time()-start)*1000:.2f}ms')"

# Using curl for HTTP services
curl -o /dev/null -s -w 'Connect: %{time_connect}\n' http://example.com:1234

When building monitoring systems like Graphite/Diamond collectors, we often need to measure pure TCP connection establishment time without protocol overhead. The standard telnet approach presents several challenges:

# Manual telnet won't work for scripting:
$ telnet example.com 80
Trying 93.184.216.34...
Connected to example.com.
Escape character is '^]'.
^]  # Requires manual interaction
telnet> close

Linux provides several built-in alternatives that work better for scripting:

Method 1: Using timeout + nc (netcat)

timeout 5 bash -c "

Method 2: Using /dev/tcp with time

$ time (exec 3<>/dev/tcp/example.com/80; exec 3<&-)
real    0m0.045s
user    0m0.001s
sys     0m0.003s

For precise measurements, combine bash's built-ins with the time command:

$ cat measure_latency.sh
#!/bin/bash
host=$1
port=$2

{ time -p bash -c "/dev/null 2>&1; } 2>&1 | \
grep real | awk '{print $2}'

# Usage:
$ ./measure_latency.sh example.com 80
0.042

For production monitoring, consider these improvements:

#!/bin/bash
# Enhanced version with timeout and error handling
TIMEOUT=5
host=$1
port=$2

result=$( { time -p timeout $TIMEOUT bash -c "/dev/null 2>&1; } 2>&1 )
status=$?

if [ $status -eq 0 ]; then
    echo $result | grep real | awk '{print $2}'
elif [ $status -eq 124 ]; then
    echo "timeout"
else
    echo "connection_failed"
fi
Tool Advantage Disadvantage
nc (netcat) Widely available May need -w timeout flag
/dev/tcp No dependencies Bash-specific
socat Very flexible Not always installed

For Diamond collector integration, you might use:

# diamond.conf snippet
[[TCPLatencyCollector]]
enabled = True
hosts = web1:80, db1:3306, cache1:11211
interval = 60
timeout = 5