使用 PowerShell 更快地测试网络端口

使用 PowerShell 更快地测试网络端口

在 Windows 8.1 中,Test-NetConnectioncmdlet 可用于检查远程系统上的网络端口状态。但是,有时它可能会不必要地变慢。我想知道是否有一些我可以调整的选项,或者我可以使用其他 PowerShell 命令来加快此过程。

Test-NetConnection如果远程系统没有响应,则可能需要大约 10 秒钟才能返回结果。每当指定一个端口时,它都会运行两个连接测试,每个测试大约需要 5 秒钟才能超时。第一个测试是基本的 ICMP 回显检查。如果系统处于离线状态,或者它(或任何中间基础设施)配置为阻止或不响应 ICMP 回显请求,则该测试将超时。第二个测试是对指定端口的实际检查。如果系统处于离线状态,或者路径上有防火墙阻止端口,则该测试将超时。

在我当前的用例中,远程系统在可靠的千兆以太网连接上仅相隔两跳。因此,任何请求的五秒超时都太过分了 - 我可能仍然可以在 30 毫秒或更短的超时时间内获得可靠的结果!此外,即使系统可能在线并且所有其他服务都可用,它也对 ICMP 回显没有响应。因此,如果我可以完全不使用 ICMP 回显测试并减少 TCP 连接测试的超时时间,以加快用于Test-NetConnection此目的的脚本的速度,那就太好了。

是否Test-NetConnection有选项可以改变这些行为?(我已经阅读了详细的帮助文件,答案似乎是否定的 - 但我很高兴有人告诉我我错过了一些东西。)或者有没有另一种方法可以使用 PowerShell 来运行相同的检查,但速度更快?

出于各种原因,我倾向于尽可能将脚本限制为使用操作系统内置的功能。假设环境是 Windows 8.1 的全新版本,已应用所有适当的 Windows 更新,并且第三方工具不是一种选择。

答案1

非常基础(超时 100 毫秒):

function testport ($hostname='yahoo.com',$port=80,$timeout=100) {
  $requestCallback = $state = $null
  $client = New-Object System.Net.Sockets.TcpClient
  $beginConnect = $client.BeginConnect($hostname,$port,$requestCallback,$state)
  Start-Sleep -milli $timeOut
  if ($client.Connected) { $open = $true } else { $open = $false }
  $client.Close()
  [pscustomobject]@{hostname=$hostname;port=$port;open=$open}
}

testport

hostname  port  open
--------  ----  ----
yahoo.com   80  True

答案2

我见过的测试 TCP 端口的最短方法是:

(New-Object System.Net.Sockets.TcpClient).ConnectAsync("google.com", 80).Wait(100)

或者

[System.Net.Sockets.TcpClient]::new().ConnectAsync("google.com", 80).Wait(100) 

等待时间以毫秒为单位。这是一种与旧版 PowerShell 2.0 兼容的方法。

答案3

您可以使用它来测试连接 -摘自PowerShell 代码存储库(作者 'BSonPosh')

“Test-Port 创建到指定端口的 TCP 连接。默认情况下,它连接到端口 135,超时时间为 3 秒。”

Param([string]$srv,$port=135,$timeout=3000,[switch]$verbose)

# Test-Port.ps1
# Does a TCP connection on specified port (135 by default)

$ErrorActionPreference = "SilentlyContinue"

# Create TCP Client
$tcpclient = new-Object system.Net.Sockets.TcpClient

# Tell TCP Client to connect to machine on Port
$iar = $tcpclient.BeginConnect($srv,$port,$null,$null)

# Set the wait time
$wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)

# Check to see if the connection is done
if(!$wait)
{
    # Close the connection and report timeout
    $tcpclient.Close()
    if($verbose){Write-Host "Connection Timeout"}
    Return $false
}
else
{
    # Close the connection and report the error if there is one
    $error.Clear()
    $tcpclient.EndConnect($iar) | out-Null
    if(!$?){if($verbose){write-host $error[0]};$failed = $true}
    $tcpclient.Close()
}

# Return $true if connection Establish else $False
if($failed){return $false}else{return $true}

您可以前往该存储库页面进行后续操作(这个答案已经是太多的复制工作了)

答案4

更快捷的方法可能是:

param($ip,$port)
New-Object System.Net.Sockets.TCPClient -ArgumentList $ip, $port

结果是:

Client              : System.Net.Sockets.Socket
Available           : 0
Connected           : True
ExclusiveAddressUse : False
ReceiveBufferSize   : 65536
SendBufferSize      : 65536
ReceiveTimeout      : 0
SendTimeout         : 0
LingerState         : System.Net.Sockets.LingerOption
NoDelay             : False

有趣的值是“已连接”

编辑:还有一个原因:Test-NetConnection 仅适用于 Powershell v5(如果我没记错的话),而此解决方案适用于 v2:)

相关内容