Тестируйте сетевые порты быстрее с помощью PowerShell

Тестируйте сетевые порты быстрее с помощью PowerShell

В Windows 8.1 Test-NetConnectionкомандлет полезен для проверки состояния сетевого порта на удаленной системе. Однако иногда он может быть неоправданно медленным. Я хотел бы узнать, есть ли какие-то параметры, которые я мог бы настроить, или альтернативная команда PowerShell, которую я мог бы использовать, чтобы ускорить этот процесс.

Test-NetConnectionможет потребоваться около 10 секунд для возврата результатов, если удаленная система не отвечает. Всякий раз, когда указан порт, он запускает два теста соединения, каждый из которых требует около 5 секунд для тайм-аута. Первый тест — это базовая проверка эха ICMP. Он будет заблокирован, если система находится в автономном режиме или если она (или любая промежуточная инфраструктура) настроена на блокировку или отсутствие ответа на запросы эха ICMP. Второй тест — это фактическая проверка указанного порта. Он будет заблокирован, если система находится в автономном режиме или если на пути есть брандмауэр, блокирующий порт.

В моем текущем варианте использования удаленная система находится всего в двух шагах от надежного соединения Gigabit Ethernet. Таким образом, пятисекундный тайм-аут для любого запроса является довольно чрезмерным — я, вероятно, все еще мог бы получить надежные результаты с тайм-аутом 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

Интересное значение — «Подключено».

edit: еще одна причина: Test-NetConnection работает только из Powershell v5 (если я правильно помню), тогда как это решение работает из v2 :)

Связанный контент