windows 自带的 ping 工具不能指定发包间隔,于是自己写了一个可以快速打 ping 包的工具
源码:
param(
[Alias("t")]
[Parameter(Mandatory=$false, Position=0)]
[string]$Target = "www.example.com",
[Alias("n")]
[Parameter(Mandatory=$false)]
[int]$Count = 10,
[Alias("s")]
[Parameter(Mandatory=$false)]
[double]$IntervalSeconds = 0.2,
[Alias("l")]
[Parameter(Mandatory=$false)]
[int]$BufferSize = 32,
[Alias("w")]
[Parameter(Mandatory=$false)]
[int]$Timeout = 4000,
[Alias("h", "?")]
[Parameter(Mandatory=$false)]
[switch]$Help,
[Alias("c")]
[Parameter(Mandatory=$false)]
[switch]$Continuous,
# 使用-v6参数强制IPv6
[Alias("v6")]
[Parameter(Mandatory=$false)]
[switch]$ForceIPv6
)
# 显示帮助信息
function Show-Help {
Write-Host "`n自定义Ping工具 - 毫秒级间隔控制" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "`n用途: 执行可调节间隔时间和包大小的Ping测试" -ForegroundColor Yellow
Write-Host "`n使用方法:" -ForegroundColor Green
Write-Host " fastping.ps1 [目标地址] [参数]"
Write-Host " fastping.ps1 [参数] [目标地址]"
Write-Host "`n参数说明:" -ForegroundColor Green
Write-Host " -t, -Target <地址> 目标IP或域名 (默认: www.example.com)"
Write-Host " -n, -Count <次数> 发送次数 (默认: 10)"
Write-Host " -s, -IntervalSeconds <秒> 间隔时间(秒) (默认: 0.2 = 200ms)"
Write-Host " -l, -BufferSize <字节> 包大小(字节) (默认: 32)"
Write-Host " -w, -Timeout <毫秒> 超时时间(毫秒) (默认: 4000)"
Write-Host " -c, -Continuous 连续模式,按Ctrl+C停止"
Write-Host " -v6, -ForceIPv6 强制使用IPv6地址"
Write-Host " -h, -?, -Help 显示此帮助信息"
Write-Host "`n使用示例:" -ForegroundColor Green
Write-Host " 基本使用:"
Write-Host " fastping.ps1 8.8.8.8"
Write-Host " fastping.ps1 -t google.com -n 20"
Write-Host " `n毫秒级间隔:"
Write-Host " fastping.ps1 192.168.1.1 -s 0.05 # 50毫秒间隔"
Write-Host " fastping.ps1 8.8.8.8 -s 0.01 # 10毫秒间隔"
Write-Host " `n控制包大小:"
Write-Host " fastping.ps1 example.com -l 64 # 64字节包"
Write-Host " fastping.ps1 example.com -l 1024 # 1KB大包测试"
Write-Host " `nIPv6测试:"
Write-Host " fastping.ps1 baidu.com -v6 # 强制使用IPv6"
Write-Host " fastping.ps1 ipv6.google.com -v6 # IPv6域名测试"
Write-Host " fastping.ps1 2001:4860:4860::8888 # 直接使用IPv6地址"
Write-Host " `n组合参数:"
Write-Host " fastping.ps1 8.8.8.8 -n 50 -s 0.1 -l 512 -w 2000"
Write-Host " fastping.ps1 google.com -c -s 0.5 # 连续ping"
Write-Host " fastping.ps1 baidu.com -v6 -n 20 -s 0.2"
Write-Host " `n帮助信息:"
Write-Host " fastping.ps1 -h"
Write-Host " fastping.ps1 -?"
Write-Host "`n注意事项:" -ForegroundColor Magenta
Write-Host " * 间隔时间精度受系统限制,约10-20毫秒"
Write-Host " * ICMP包最大有效负载通常为1472字节(1500-20-8)"
Write-Host " * 连续模式中按 Ctrl+C 停止测试"
Write-Host " * 首次运行可能需要: Set-ExecutionPolicy RemoteSigned"
Write-Host " * 使用 -v6 参数时,确保系统已启用IPv6且目标支持IPv6"
exit 0
}
# 如果请求帮助,显示帮助信息并退出
if ($Help) {
Show-Help
}
# 解析目标地址的函数(保持不变)
function Resolve-TargetAddress {
param(
[string]$TargetName,
[bool]$ForceIPv6
)
# 检查是否是IP地址
$ipAddress = $null
if ([System.Net.IPAddress]::TryParse($TargetName, [ref]$ipAddress)) {
# 已经是IP地址
if ($ForceIPv6 -and $ipAddress.AddressFamily -ne [System.Net.Sockets.AddressFamily]::InterNetworkV6) {
Write-Host "错误: 目标地址 '$TargetName' 不是IPv6地址,但使用了IPv6模式" -ForegroundColor Red
exit 1
}
return $ipAddress
}
# 解析域名
Write-Host "正在解析: $TargetName ..." -ForegroundColor DarkGray
try {
$addresses = [System.Net.Dns]::GetHostAddresses($TargetName)
if ($addresses.Count -eq 0) {
Write-Host "错误: 无法解析 '$TargetName'" -ForegroundColor Red
exit 1
}
# 根据IPv6参数筛选地址
if ($ForceIPv6) {
$ipv6Addresses = $addresses | Where-Object { $_.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetworkV6 }
if ($ipv6Addresses.Count -eq 0) {
Write-Host "错误: 目标 '$TargetName' 没有IPv6地址" -ForegroundColor Red
Write-Host "可用地址:" -ForegroundColor Yellow
$addresses | ForEach-Object { Write-Host " $($_.ToString()) ($($_.AddressFamily))" }
exit 1
}
# 优先选择全局IPv6地址
$selectedAddress = $ipv6Addresses | Where-Object {
$_.ToString() -notmatch '^fe80:' -and $_.ToString() -notmatch '^::1$'
} | Select-Object -First 1
if (-not $selectedAddress) {
$selectedAddress = $ipv6Addresses[0]
}
Write-Host "已选择IPv6地址: $($selectedAddress.ToString())" -ForegroundColor Cyan
return $selectedAddress
}
else {
# 默认优先选择IPv4地址
$ipv4Addresses = $addresses | Where-Object { $_.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork }
if ($ipv4Addresses.Count -gt 0) {
$selectedAddress = $ipv4Addresses[0]
Write-Host "已选择IPv4地址: $($selectedAddress.ToString())" -ForegroundColor Cyan
return $selectedAddress
}
else {
# 只有IPv6地址时使用IPv6
Write-Host "注意: 目标 '$TargetName' 只有IPv6地址,自动使用IPv6" -ForegroundColor Yellow
$selectedAddress = $addresses[0]
Write-Host "已选择地址: $($selectedAddress.ToString())" -ForegroundColor Cyan
return $selectedAddress
}
}
}
catch {
Write-Host "错误: 解析 '$TargetName' 时出错: $_" -ForegroundColor Red
exit 1
}
}
# 连续模式处理
if ($Continuous) {
$Count = [int]::MaxValue
Write-Host "`n进入连续ping模式 (按 Ctrl+C 停止)..." -ForegroundColor Yellow
}
# 解析目标地址
$resolvedAddress = Resolve-TargetAddress -TargetName $Target -ForceIPv6 $ForceIPv6
$addressFamily = if ($resolvedAddress.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetworkV6) { "IPv6" } else { "IPv4" }
# 显示测试信息
Write-Host "`n自定义Ping测试开始" -ForegroundColor Cyan
Write-Host "目标: $Target ($($resolvedAddress.ToString()) - $addressFamily)" -ForegroundColor White
Write-Host "设置: $Count 次, ${IntervalSeconds}s 间隔, ${BufferSize}字节包" -ForegroundColor White
if ($ForceIPv6) {
Write-Host "模式: IPv6强制模式已启用" -ForegroundColor Yellow
}
Write-Host "`n" + ("-" * 60) + "`n" -ForegroundColor DarkGray
# 创建Ping对象和缓冲区
$ping = New-Object System.Net.NetworkInformation.Ping
$buffer = [byte[]]::new($BufferSize)
for ($i=0; $i -lt $BufferSize; $i++) {
$buffer[$i] = 97 # ASCII 'a'
}
# 统计变量
$successCount = 0
$totalTime = 0
$minTime = [int]::MaxValue
$maxTime = 0
$startTime = Get-Date
# 执行Ping循环
for ($i=1; $i -le $Count; $i++) {
$timestamp = Get-Date -Format "HH:mm:ss.fff"
Write-Host "[$timestamp] #$i" -NoNewline -ForegroundColor DarkGray
if ($Continuous -and $i -eq 1) {
Write-Host " (连续模式)" -NoNewline -ForegroundColor Yellow
}
Write-Host " 发送 ${BufferSize}字节..." -NoNewline
try {
$reply = $ping.Send($resolvedAddress, $Timeout, $buffer)
if ($reply.Status -eq "Success") {
$successCount++
$totalTime += $reply.RoundtripTime
if ($reply.RoundtripTime -lt $minTime) { $minTime = $reply.RoundtripTime }
if ($reply.RoundtripTime -gt $maxTime) { $maxTime = $reply.RoundtripTime }
# 根据延迟显示不同颜色
$color = "Green"
if ($reply.RoundtripTime -gt 100) { $color = "Yellow" }
if ($reply.RoundtripTime -gt 200) { $color = "Red" }
Write-Host " 回复自 $($reply.Address): 时间=$($reply.RoundtripTime)ms TTL=$($reply.Options.Ttl)" -ForegroundColor $color
} else {
Write-Host " 请求超时 ($($reply.Status))" -ForegroundColor Red
}
}
catch [System.Net.NetworkInformation.PingException] {
Write-Host " Ping错误: $($_.Exception.InnerException.Message)" -ForegroundColor Red
# 特定于IPv6的错误处理
if ($ForceIPv6 -and $_.Exception.InnerException.Message -match "No such host is known") {
Write-Host "提示: 请确保IPv6已启用且目标支持IPv6" -ForegroundColor Yellow
}
}
catch {
Write-Host " 错误: $_" -ForegroundColor Red
}
# 最后一次不等待(连续模式除外)
if ($i -ne $Count) {
Start-Sleep -Seconds $IntervalSeconds
}
# 连续模式每10次显示一次统计
if ($Continuous -and $i % 10 -eq 0 -and $i -gt 0) {
$elapsed = (Get-Date) - $startTime
Write-Host "`n[统计] 已发送: $i, 成功: $successCount, 成功率: $([math]::Round($successCount/$i*100,1))%" -ForegroundColor Cyan
Write-Host "`n" + ("-" * 60) + "`n" -ForegroundColor DarkGray
}
}
# 最终统计信息
$endTime = Get-Date
$duration = $endTime - $startTime
Write-Host "`n" + ("=" * 60) -ForegroundColor Cyan
Write-Host "Ping 统计信息" -ForegroundColor Cyan
Write-Host ("-" * 60) -ForegroundColor Cyan
Write-Host "目标: $Target ($($resolvedAddress.ToString()))"
Write-Host "地址类型: $addressFamily"
Write-Host "测试时间: $($duration.ToString('mm\:ss\.fff')) (开始: $($startTime.ToString('HH:mm:ss')), 结束: $($endTime.ToString('HH:mm:ss')))"
Write-Host "发送: $Count, 成功: $successCount, 丢失: $($Count - $successCount)"
if ($successCount -gt 0) {
$lossRate = [math]::Round(($Count - $successCount) / $Count * 100, 1)
$avgTime = [math]::Round($totalTime / $successCount, 2)
Write-Host "丢包率: ${lossRate}%"
Write-Host "往返时间(ms): 最小=${minTime}, 最大=${maxTime}, 平均=${avgTime}"
# 延迟评价
if ($avgTime -lt 30) { $rating = "优秀" }
elseif ($avgTime -lt 100) { $rating = "良好" }
elseif ($avgTime -lt 200) { $rating = "一般" }
else { $rating = "较差" }
$ratingColor = @{
"优秀" = "Green"
"良好" = "Green"
"一般" = "Yellow"
"较差" = "Red"
}
Write-Host "网络质量: $rating" -ForegroundColor $ratingColor[$rating]
}
Write-Host "包大小: ${BufferSize}字节, 间隔: ${IntervalSeconds}s"
Write-Host ("=" * 60) -ForegroundColor Cyan