Test-CWJTCPPort.psm1
|
function Test-CWJTCPPort { param( [Parameter(Mandatory=$true, Position=0)] [string] $ComputerName, #TODO: allow for array of hostnames/ports [Parameter(Mandatory=$true, Position=1)] [uint16] $Port, [Parameter(Mandatory=$false, Position=2)] [int] $Timeout = 5000, [Parameter(Position=3)] [switch] $ReturnObject = $false, [Parameter(Mandatory=$false)] [switch] $DontFragment, [Parameter(Mandatory=$false)] [ValidateSet('Socket', 'TcpClient')] [string] $ConnectionType = 'Socket' ) try { $DestinationIP = [System.Net.Dns]::GetHostAddresses($ComputerName)[0].IPAddressToString } catch { throw "Unable to resolve address: $ComputerName" } $DestinationEndPoint = New-Object System.Net.IPEndPoint ([ipaddress]$DestinationIP), $Port $AddressFamily = $DestinationEndPoint.AddressFamily try { if($ConnectionType -eq 'Socket') { $SocketType = [System.Net.Sockets.SocketType]::Stream #TODO: come back to explore other possible values $ProtocolType = [System.Net.Sockets.ProtocolType]::Tcp $tcpclient = New-Object System.Net.Sockets.Socket $AddressFamily, $SocketType, $ProtocolType #TODO: change name to $Socket $tcpclient.LingerState = New-Object System.Net.Sockets.LingerOption -ArgumentList $false, 0 # Don't set DontFragment on IPv6 addresses, exception returned...why? #TODO: can I do this always if I'm using socket()? if($AddressFamily -eq 'InterNetwork') { $tcpclient.DontFragment = $DontFragment } } else { $tcpclient = New-Object System.Net.Sockets.TcpClient -ArgumentList $AddressFamily $tcpclient.Client.LingerState = New-Object System.Net.Sockets.LingerOption -ArgumentList $false, 0 # Don't set DontFragment on IPv6 addresses, exception returned...why? #TODO: can I do this always if I'm using socket()? if($AddressFamily -eq 'InterNetwork') { $tcpclient.Client.DontFragment = $DontFragment } } $connection = $tcpclient.BeginConnect($DestinationIP, $Port, $null, $null) $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $success = $connection.AsyncWaitHandle.WaitOne($Timeout, $true) $ResponseTime = $Stopwatch.ElapsedMilliseconds if($tcpclient.Connected) { $status = 'Open' $tcpclient.EndConnect($connection) } else { if($success) { $status = 'Closed' } else { $status = 'Filtered' } } if($ReturnObject) { [pscustomobject]@{ ComputerName = $ComputerName Port = $Port Status = $status ResponseTime = $ResponseTime } } else { if($status -eq 'Open') { return $true } else { return $false } } } catch { Write-Error $_.tostring() } finally { $tcpclient.Dispose() } } <# #Repro of retransmit and ignored RSTs $IP = '192.168.1.1' $Port = 0 $Timeout = 1000 $Socket = New-Object System.Net.Sockets.TcpClient -ArgumentList 'InterNetwork' $connection = $Socket.BeginConnect($IP, $Port, $null, $null) $success = $connection.AsyncWaitHandle.WaitOne($Timeout, $true) if($Socket.Connected) { $status = 'Open' } elseif($success) { $status = 'Closed' } else { $status = 'Filtered' } $Socket.Dispose() #> #TODO: use $socket.localenpoint to show local ip/port |