# Latency probe: UDP DNS RTT + ICMP RTT to 1.1.1.1, plus NIC throughput, every ~200 ms. # Read-only. Stops when stop.flag appears next to this script. $dir = Split-Path -Parent $MyInvocation.MyCommand.Path $out = Join-Path $dir 'probe.csv' $stop = Join-Path $dir 'stop.flag' if (Test-Path $stop) { Remove-Item $stop } 'ts,udp_ms,icmp_ms,tx_mbps,rx_mbps' | Out-File $out -Encoding ascii $nic = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | Where-Object { $_.Name -eq 'Ethernet' } $ping = New-Object System.Net.NetworkInformation.Ping $udp = New-Object System.Net.Sockets.UdpClient $udp.Client.ReceiveTimeout = 1000 $udp.Connect('1.1.1.1', 53) $q = [byte[]](0,0, 1,0, 0,1, 0,0, 0,0, 0,0, 7) + [Text.Encoding]::ASCII.GetBytes('example') + [byte[]](3) + [Text.Encoding]::ASCII.GetBytes('com') + [byte[]](0, 0,1, 0,1) $ep = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0) $sw = New-Object System.Diagnostics.Stopwatch $s0 = $nic.GetIPStatistics(); $t0 = [DateTime]::UtcNow $id = 0 while (-not (Test-Path $stop)) { $id = ($id + 1) % 65536; $q[0] = [byte]($id -shr 8); $q[1] = [byte]($id -band 255) $udpMs = -1 try { $sw.Restart(); [void]$udp.Send($q, $q.Length) do { $r = $udp.Receive([ref]$ep) } while ($r[0] -ne $q[0] -or $r[1] -ne $q[1]) $sw.Stop(); $udpMs = [math]::Round($sw.Elapsed.TotalMilliseconds, 1) } catch { $udpMs = -1 } $icmpMs = -1 try { $p = $ping.Send('1.1.1.1', 1000); if ($p.Status -eq 'Success') { $icmpMs = $p.RoundtripTime } } catch {} $s1 = $nic.GetIPStatistics(); $t1 = [DateTime]::UtcNow $dt = ($t1 - $t0).TotalSeconds $tx = [math]::Round(($s1.BytesSent - $s0.BytesSent) * 8 / 1e6 / $dt, 1) $rx = [math]::Round(($s1.BytesReceived - $s0.BytesReceived) * 8 / 1e6 / $dt, 1) $s0 = $s1; $t0 = $t1 "{0},{1},{2},{3},{4}" -f (Get-Date -Format 'HH:mm:ss.fff'), $udpMs, $icmpMs, $tx, $rx | Out-File $out -Append -Encoding ascii $wait = 200 - [int]$sw.Elapsed.TotalMilliseconds if ($wait -gt 0) { Start-Sleep -Milliseconds $wait } } $udp.Close()